• fork() system call

    • 프로세스 생성을 위한 호출

    • fork는 함수를 호출한 프로세스를 복사하는 기능을 하는데, 이때 부모의 프로세스와 자식 프로세스가 나뉘어 실행된다.

    • 부모프로세스 → 자식프로세스의 pid / 자식프로세스 → 0 리턴

      • fork()함수 한번으로 둘 다 리턴 가능 But. 둘의 출력 순서는 정해지지 않음 (자식 먼저 나올수도 부모 먼저나올수도 있음)

      image.png

  • wait() system call

    • 자식 프로세스가 끝날때까지 기다리는 함수이다.

      • 부모프로세스에 해당하는 if구절의 바디에 wait()걸어두면, 자식프로세스가 출력되고 끝나면, 부모프로세스가 출력된다.
        • 이렇게 되면 fork를 호출했을때와 같이 리턴 순서가 정해지지 않는 문제를 해결할 수 있다.

      image.png

  • exec() system call

    • 자기 자신(부모)이 아닌 다른 프로그램을 실행해야 할 때 사용
    • 새로운 프로세스는 생성하지 않으며, 현재 실행 중인 프로그램을 다른 실행 중인 프로그램으로 대체하는 것
  • CPU 가상화

    • OS는 많은 가상의 cpu가 존재하는 것과 같은 환영을 만들어냄
      • Time sharing 시간 공유 : 자원이 한정되있는 상태에서 하나의 프로세스를 실행하고 멈췄다가 다른 프로세스를 실행하고를 반복(엄청빠르게) ex) 교수님의 볼펜 돌려막기 생각하자
  • 프로세스 Process

    • 실행중인 프로그램을 의미한다.
    • 프로그램이 실행되면, 이 프로그램의 명령어들과 데이터가 메모리에 적재되고 이것이 프로세스가 된다!
    • 메모리, 레지스터로 구성됨
      • 메모리 : 명령어, 데이터 섹션
      • 레지스터 : 프로그램 카운터값(다음 명령어의 주소값), 스택 포인터
    • 동일한 프로그램에서 여러개의 프로세스를 가질 수 있다.
    • 프로세스 API
      • Create : fork 새로운 프로세스 만드는
      • Destroy : system call을 kill하는 (exit = 자기자신)
      • Wait : 디버깅할때 유리 → (걸어놓고 다른 것들을 모니터링)
      • Miscellaneous control : 프로세스 중단 후 재개하도록 하는
      • Status : 프로세스의 상태 보여주는
    • 프로세스의 생성과정
      1. 프로그램 코드를 메모리공간에 로드하고, 프로세스의 주소공간에 넣는다.
        • 프로그램은 처음에 실행가능한 형식으로 Disk에 담겨져있다.
      2. 런타임 스택이 할당된다. (스택에 로컬변수, 매개변수 할당)
      3. 프로그램의 힙이 생성된다.(동적할당된 데이터를 위해)
      4. OS는 다른 초기화 작업을 수행함(입출력을 위한 준비)
      5. main()함수와 같은 엔트리 포인트에서 프로그램 실행
    • 프로세스의 상태
      • Running
        • CPU(프로세스의 주도권)을 잡고 명령어를 실행중인 상태
      • Ready
        • CPU를 기다리는 상태(당장 물리적인 메모리에 프로그램이 올라와있는 상태 등의 프로세스의 주도권을 잡지 않은 것을 제외하고는 다른 조건 모두 만족한 상태)
      • Blocked
        • wait, sleep에 해당
        • CPU 자원을 가질 수 없는 상태
        • 프로세스가 I/O 등의 event를 기다리는 상태
          • I/O 를 요청받으면 즉시 Blocked상태가 되고, 다른 프로세스가 프로세서를 사용한다.(사용을 안하기에)
      • Unused : 사용하지 않는 것(Pid도 존재하지 않음) → 출력x
      • Embryo : 아무것도 건들지 않은 초기 상태
      • Zombie : fork같은 것으로 프로세스를 생성시킴 → 부모/자식이 존재할텐데, 자식이 죽으면 다잉메세지로 PCB에 자식의 정보를 담아두는데 부모가 이를 확인하여 죽이지 않고 방치한 상태
        • 계속 방치하면 나중에 init process(제일 원초적인 프로세스)가 부모프로세스까지 없앰
      • Unused, Embryo, Zombie는 그냥 읽어보기
      • Running, Ready, Blocked의 변환

    image.png

    • Data structures
      • 운영체제는 정보와 관련된 몇몇의 중요한 데이터 구조를 갖고있다.
        • 프로세스 리스트
          • Ready process - queue에 존재
          • Blocked process - queue에 존재
          • Running process - 따로 존재
        • 레지스터 context
          • 실행중이던 프로세스를 중단하면 레지스터값을 PCB에 저장했다가 재개하면 다시 사용함
      • PCB(Process Control Block)
        • 각 프로세스의 정보(레지스터 값)를 담은 C구조
        • 프로세스가 죽으면 PCB작동
    • 어떻게 CPU가 효율적으로 가상화를 할 수 있을까?
      • 운영체제는 타임쉐어링을 위해 물리적인 cpu 를 공유할 필요가 있다.
      • 운영체제가 실행되려면 cpu자원에 대한 통제권을 필요로함
        • 프로그램도 실행되려면 cpu자원이 필요하기 때문에 운영체제가 cpu자원에 대한 주도권(통제권)을 넘겨줌
          • 어떠한 제한 없이 프로그램이 주도권을 넘겨받아 실행되도록 냅두면, 운영체제는 cpu자원에 대한 통제권을 다시 돌려받지 못할 수도 있음!!! (문제점)
      • 문제1 : 제한된 작동
        • OS도 디스크에 입출력을 요청하거나 cpu, 메모리 자원에 접근하려면 통제권이 필요하다
          • 해결책은 유저모드와 커널모드를 통한 제한된 통제권을 주는 방법을 사용하는 것이다.
          • Trap 시스템콜
            • 커널로 점프한다. 권한을 커널모드로 올린다.
              • Return-from-trap 시스템콜
                • 트랩을 호출한 프로그램으로 돌아온다.
                • 권한을 유저모드로 다시 낮춘다.
            • 트랩을 통해 권한을 주고 받고 함
              • 이 방법도 문제 있음 → 주고받기가 끝나지x
                • 해결책은 reboot 재시작
      • 문제2 : 프로세스 사이에서의 전환
        • OS가 다시 통제권을 잡아서 프로세스 간의 전환이 생기도록 하려면 어떻게 해야 할까?
          • 협조적인 방법 : system call 을 기다린다 → 좋은 방법은 아님
            • trap system call을 부르기전까지 프로세스는 무한 루프(트랩주고받기)에 갇힌다. 해결책이 리부트하는 방법밖에 없다.
          • 비협조적인 방법 : OS가 통제권을 뺏어온다.
            • Timer interrupt
              • OS가 타이머를 시작하여, 일정 시간이 상승하면 현재 프로세스를 중단한 후 프로그램의 상태를 충분히 저장하고, 통제권을 다시 갖는 방법
              • CPU통제권을 다시 얻을 수 있는 능력을 OS에게 주는 방법이다!
      • Context Swtich