Process Management

[프로세스 관리에 대해 알아보자!]

프로세스 관리

프로세스 생성

  • 부모 프로세스가 자신을 복제(프로세스의 context를 모두 복사)해서 자식 프로세스를 생성
  • 프로세스의 계층 구조가 트리 형태로 형성
  • 프로세스가 실행되려면 자원(CPU, 메모리 등)이 필요하기 때문에 자원을 운영체제로부터 받는다.
  • 자원의 공유
    • 부모 프로세스와 자식 프로세스가 모든 자원을 공유하는 모델
    • 일부를 공유하는 모델
    • 전혀 공유하지 않는 모델
    • 부모 프로세스가 자식 프로세스를 낳으면 그때부터는 별도의 프로세스이기 때문에 서로 CPU와 메모리를 얻기위해 경쟁하는 사이가 되기 때문에 원칙적으로는 자원을 공유하지 않는다.
  • 수행(Execution) 모델
    • 부모 프로세스와 자식 프로세스가 공존하며 수행되는 모델
    • 자식 프로세스가 종료(terminate)될 때까지 부모 프로세스가 기다리는(blocked) 모델
  • 주소 공간
    • 자식 프로세스는 일단 부모 프로세스의 공간을 복제한 뒤(fork()), 그 공간에 새로운 프로그램을 올린다.(exec())

Copy-on-write(COW) 기법

  • write가 발생했을 때!!!! 그 때 copy를 하겠따!!

  • 자식 프로세스가 부모 프로세스를 그대로 복제하면 결국엔 메모리에 두 개가 똑같이 올라간다. 이는 메모리의 낭비를 일으키기 때문에 일단 똑같은 내용을 만든다고 하면 당장에 복제할 필요는 없다.
  • Linux나 일부 모델에서는 부모 프로세스의 모든것을 복제하지 않고 공유 가능한 것들은 일단 공유해본다.
  • 부모 프로세스를 복제해서 주소공간이 만들어지는게 원칙이지만 Linux나 좀 더 효율적인 운영체제에서는 복제하지 않고 일단 부모 프로세스의 주소공간을 공유하는 상태를 가진다.
  • 결국 별개의 프로세스이기 때문에 stack에 쌓이는 내용이나 함수 호출 등 다른 부분이 발생하여 각자의 길을 가게 되면 그제서야 공유하던 부모의 주소공간을 복제한다.
  • 주소공간을 복제할 때에도 전부를 복제하는게 아님.. 물리적인 메모리에 code, data, stack이 잘게 쪼개져서 필요한 부분만 올라가기 때문에.. 공유하는 내용과 다른 부분만 복제해서 사용한대..

ex) fork() system call

int main()
{
    int pid;
    pid = fork();
    if(pid == 0)		/* this is child */
        printf("\n Hello, I am child!\n");
    else if(pid > 0)	/* this is parent */
        printf("\n Hello, I am, parent!\n");
}
  • 처음에 부모 프로세스가 실행을 하다가 fork()를 통해 자식 프로세스를 만들고 나머지 아랫부분을 수행한다.
  • 자식 프로세스는 부모 프로세스의 문맥을 복제하기 때문에 fork() 함수가 끝난 뒤이기 때문에 if문부터 수행한다.
  • ISSUE
    1. 복제를 해놨더니 지가 복제본이 아니라 원본이라고 주장하면서 부모 프로세스를 복제본 취급할 수 있다.
    2. 부모 프로세스를 복제했기 때문에 모두 같은 일을 하게 된다.
  • 이를 방지하기 위해 fork()함수의 return 값을 다르게 준다.
  • 부모 프로세스는 자식 프로세스의 pid(양수)를 얻게 되고, 자식 프로세스는 0을 얻는다.
  • 이를 통해 부모 프로세스와 자식 프로세스가 서로 다른 일을 하게 할 수 있다.

ex) exec() system call

기존 프로그램

int main()
{
    int pid;
    pid = fork();
    if(pid == 0) {		/* this is child */
        printf("\n Hello, I am child! Now I'll run date \n");
        execlp("/bin/date", "/bin/date", (char *)0);
    }
    else if(pid > 0)	/* this is parent */
        printf("\n Hello, I am, parent!\n");
}

date 프로그램

int main()
{
    printf("\n I am date program! \n");
}
  1. 기존 프로그램에서 부모 프로세스가 fork()를 하여 자식 프로세스가 새로 생긴다.
  2. 자식 프로세스는 pid가 0이기 때문에 Hello, I am child! Now I'll run date을 print하고 execlp함수를 만나게 된다.
  3. execlp에서 date 프로그램을 자식 프로세스에게 덮어씌우고 date 프로그램을 실행하게 한다. -> 자식 프로세스는 기존 프로그램의 execlp이후의 코드를 실행할 수 없다.


프로세스 종료

자발적인 프로세스 종료(exit)

  • 보통은 프로세스가 종료될 때 exit이라는 system call을 통해서 종료한다.

  • 명시적으로 exit을 수행할 수도 있고, 프로그램에 명시적으로 적어주지 않아도 main 함수가 리턴되는 위치에 컴파일러가 넣어준다.

  • 프로세스의 구조에서는 항상 자식 프로세스가 먼저 죽고나서 부모 프로세스가 죽는 구조이기 때문에 자식 프로세스가 부모 프로세스에게 output data를 보낸다.(wait)

  • 종료된 자식 프로세스들의 각종 자원들이 운영체제에게 반납된다.

비자발적인 프로세스 종료(abort)

  • 사람이 키보드로 kill, break 하는 경우
  • 어떤 자원의 할당 한계치를 넘어섰을 때 부모 프로세스가 강제로 자식 프로세스를 종료시킨다.
  • 더 이상 자식 프로세스에게 시킬 일이 없을 때 강제로 자식 프로세스를 종료시킨다.
  • 부모 프로세스가 exit하는 경우, 자식 프로세스가 먼저 죽어야 되기 때문에 부모 프로세스가 낳은 모든 자식 프로세스를 먼저 종료시킨 뒤 부모 프로세스가 종료된다.
  • 가장 아래 자식 프로세스부터 단계적인 종료가 이루어진다.

wait() system call

  • 프로세스 A가 wait() system call을 호출하면
    • 커널은 child가 종료될 때까지 프로세스 A를 sleep시킨다.(block)
    • Child process가 종료되면 커널은 프로세스 A를 깨운다(ready)
int main()
{
	int childPID; 
    childPID = fork();
    if(childPID == 0)
        printf("\n Hello, I am child!\n");
    else
        wait();
}


프로세스 간 협력

  • 독립적 프로세스(Independent process)
    • 프로세스는 각자의 주소 공간을 가지고 수행되므로 원칙적으로 하나의 프로세스는 다른 프로세스의 수행에 영향을 미치지 못함
  • 협력 프로세스(Cooperating process)
    • 프로세스 협력 메커니즘을 통해 하나의 프로세스가 다른 프로세스의 수행에 영향을 미칠 수 있음

프로세스 간 협력 메커니즘(IPC:Interprocess Communication)

  • Message Passing
    • 프로세스 사이에 공유 변수(shared variable)를 일체 사용하지 않고 통신하는 시스템
    • 프로세스는 자신의 주소 공간밖에 보지 못하기 때문에 다른 프로세스에게 메시지를 직접 보낼 수 없어 커널을 통해 메시지를 전달한다.
    • Direct Communication
      • 통신하려는 프로세스의 이름을 명시적으로 표시
      • Send(A, message) -> Receive(B, message)
    • Indirect Communication
      • mailbox(또는 port)를 통해 메시지를 간접적으로 전달
      • Send(M, message) -> Mailbox -> Receive(M, message)
  • Shared Memory
    • 서로 다른 프로세스 간에도 일부 주소 공간을 공유하게 한다.
    • 서로 자신만의 주소공간을 가지고 있지만, 물리적인 메모리에 매핑할때 일부분을 공유할 수 있도록 매핑한다.
    • 커널에게 share를 한다는 system call을 통해 매핑을 먼저 해놓아야 한다.
  • thread
    • 스레드는 사실상 하나의 프로세스이므로 프로세스 간 협력으로 보기는 어렵지만, 동일한 process를 구성하는 스레드들 간에는 주소 공간을 공유하므로 협력이 가능하다.

© 2019. All rights reserved.

Powered by Hydejack v8.5.2