본문 바로가기

Dev.Basic/운영체제

[OS] 4. Process Management

Chapter 4. Process Management


누가 프로세스를 생성하는가?

부모 프로세스가 자식 프로세스를 생성한다.

부모 프로세스 하나가 여럿의 자식 프로세스를 생성할 수 있다.

이는 트리 형태로 부모-자식 관계가 나타난다.

프로세스는 기본적으로 CPU자원을 할당받고 본인의 일을 수행하는 숙명이다.

결국 부모 프로세스로부터 생성된 자식 프로세스는 부모 프로세스와 CPU자원을 얻으려는 경쟁 구도가 형성된다.

운영체제로부터 받은 CPU자원을 부모 프로세스와 공유하는 경우도 있지만,

일반적으로는 공유하지 않는 모델로 서로 경쟁하는 구도가 형성된다.


그렇다면 부모 프로세스는 누가 생성하는가?

사용자가 프로그램을 실행시키면 운영체제를 통해서 생성된다.


프로세스 생성과정

자식은 부모의 공간을 복사한다.

이를 복제 생성된다고 말한다.

부모의 공간이란 프로세스 문맥을 의미한다.

Address Space(OS data, binary) & code, data, stack + PC까지 복제를 해서 태어난다.

그리고 자식 프로세스는 복제한 공간에 새로운 프로그램을 올린다.

즉 자식 프로세스 생성과정을 2단계로 나눌 수 있다.

1단계 : 부모 프로세스를 복제하는 단계 = fork ( )

2단계 : 복제한 공간에 새로운 프로그램을 올리는 단계 = exec ( )

이러한 과정을 거쳐 서로 다른 프로그램들이 컴퓨터에 존재하게 된다.

프로세스의 생성은 시스템 콜을 통해 요청받아 생성되므로 운영체제에 의해서만 생성이 가능하다.



프로세스와 관련된 시스템 콜

fork( ) 시스템 콜

일단 복제 생성을 한 다음에, exec( ) 시스템 콜을 통해 복제한다.

기본에 있던 구조를 빌리는 개념.

code>


1
2
3
4
5
6
7
8
9

int main() { int pid; // parent Id pid = fork( ); // Request to OS if(pid == 0) printf("Hello, I am Child!\n"); else if (pid >0) printf("Hello, I am Parent!\n"); }


위와 같은 코드가 존재한다.

부모 프로세스를 나타낸다.

이 때, fork 명령어를 통해서 자식 프로세스를 생성해달라고 운영체제에게 시스템 콜 요청을 보낸다.

운영체제가 그 요청을 받아들이고 자식 프로세스를 생성하게 되면, 위와 똑같은 코드가 하나 더 생성된다. 

복제된 코드는 자식 프로세스가 되는 것이다.

이 자식 프로세스의 코드는 맨 윗줄은 int main()부터 실행되지 않는다.

부모 프로세스로부터 복제해올 때, PC값도 복제해왔기 때문이다.

부모 프로세스의 PC값은 fork 를 완료한 시점을 가리키고 있었으므로,

자식 프로세스도 자신이 그 부분까지 실행했다고 생각하고 그 다음 코드부터 수행한다.


부모 프로세스와 자식 프로세스가 코드가 동일하면 어떻게 구분하는가?

Process Control Block 구조에서 각 프로세스에는 각각의 id값이 있었다.

pid값으로 프로세스를 구분하게 된다.

부모 프로세스는 pid 값이 양수이고,

자식 프로세스는 pid 값이 0이다.


 

exec ( ) 시스템 콜

1

2

3 4

5 6 7 8 9

10 11

int main() { int pid; // parent Id pid = fork( ); // Request to OS if(pid == 0){ printf("\n Hello, I am Child!\n"); execlp("/bin/data", "/bin/data", (char *) 0); } else if (pid >0) printf("\n Hello, I am Parent!\n"); }

exec ( ) 명령어가 추가되었다.

이렇게 도면 main 함수의 처음부터 실행하게 된다.

그러므로 자연스럽게 exec 명령어 이후에 있는 코드들은 영원히 실행될 수 없다.

이 코드에서는 "Hello, I am Parent !" 가 출력되지 않는 것이다.

한번 exec 명령어를 수행하게 되면 돌이킬 수 없다.



wait ( ) 시스템 콜

프로세스 A 가 wait( ) 시스템 콜을 호출하면

운영체제는 그 요청을 받고 프로세스 A의 자식 프로세스가 종료될 때까지 프로세스 A를 sleep시킨다.(blocked 상태)

자식 프로세스가 종료되면(자식 프로세스의 코드가 모두 수행되면) 커널은 프로세스 A를 깨운다(blocked -> ready상태) 

즉, wait( ) 시스템 콜은 자식 프로세스가 종료될 때까지 잠을 자게 하는 명령어이다.

예를 들면 이런 것이다.

명령 프롬프트를 실행시키면 Shell prompt 상에서 명령어를 입력할 수 있다.

이 때, 이미 shell이라는 프로그램이 실행되어 있는 상태이다.

명령어를 입력하여 실행시킬 프로그램을 실행시키게 되면,

이미 실행되어져 있던 shell이란 프로그램은 wait( )콜이 불러지면서

실행시킨 프로그램이 종료될 때까지 blocked 상태가 된다.


exit ( ) 시스템 콜

프로세스를 종료시키는 시스템 콜이다.

프로세스가 마지막 명령을 수행한 후 운영체제에게 이를 알려주면 이 명령어가 수행된다.

C언어 상에서는 사용자가 입력해주지 않아도 중괄호를 닫을 때 컴파일러가 자동으로 삽입하는 명령어이다.

물론 명시적으로 해줘도 된다.

프로세스의 세계에서는 일단 자식 프로세스가 먼저 죽어야 한다.

그래야 부모 프로세스가 종료될 수 있다.

종료되면서 프로세스들은 각종 자원을 운영체제에게 반납한다.



비자발적 종료 ( 강제 종료 )

프로세스가 강제 종료되는 경우가 몇 가지 존재한다.

1. 자식 프로세스가 할당 자원의 한계치를 넘어선 경우

2. 자식에게 할당된 태스크가 더 이상 필요하지 않는 경우

3. 부모가 자발적 종료를 하는 경우에 자식을 모두 강제종료 시켜야하는 경우

4, 외부에서 사람이 키보드로 kill, break를 입력하여 종료시키는 경우



프로세스 간 협력

프로세스의 독립성(독립적 프로세스 : Independent process)

프로세스는 각자의 주소공간을 갖고 수행되므로 원칙적으로 하나의 프로세스는 다른 프로세스의 수행에 영향을 끼치지 못한다.


프로세스의 협력성(협력 프로세스 : Cooperating process)

경우에 따라서는 협력을 해야지만 효율성이 높아지는 경우가 생긴다.

그럴 경우 프로세스 협력 매커니즘을 통해 하나의 프로세스가 다른 프로세스의 수행에 영향을 미칠 수 있게 된다.



프로세스간 협력 매커니즘(IPC : InterProcess Communication)

메세지를 전달하는 방법 (= message passing)

메세지를 직접 전달하는 방법은 없다.

중간에 커널을 통해 전달한다. 이 때 커널이 메신저 역할을 하게 된다.

Direct Communication

통신하려는 프로세스의 이름을 명시적으로 표시하는 방법

Indirect Communication

커널에 존재하는 mailbox(or port)를 통해 메시지를 전달하는 방법.

박스 같은 곳에 메시지를 넣어두고 누구한테 보낼지는 적지 않는 것이다.


주소 공간을 공유하는 방법(=shared memory)

서로 다른 프로세스 간에도 일부 주소 공간을 공유하게 하는 매커니즘이다.

물리적인 메모리에 매핑할 때부터 공유하도록 매핑해둔 것이다.

이 방법을 사용하는 두 프로세스는 신뢰성이 높은 프로세스여야 한다.


cf)

CPU 수행단위인 스레드는 사실상 하나의 프로세스 안에 존재하는 것이므로

프로세스 간 협력이라고 보기는 어렵지만 동일한 프로세스를 구성하는 스레드 간에는

주소 공간을 완전히 공유해야 협력이 가능하다.

그리고 이것을 스레드 간의 협력이라고 한다.



Chapter 4. 끝

이 포스팅은 이화여대 반효경 교수님 강의를 듣고 요약한 내용을 담고 있습니다.