Shine's dev log

프로세스 생성, 대체, 종료 본문

운영체제

프로세스 생성, 대체, 종료

dong1 2020. 4. 9. 23:46

우리가 사용중인 컴퓨터는 여러개의 프로세스들이 실행되고있다.

 

사실 이 여러개의 프로세스는 독립적으로 생성된 것이 아니라

 

처음 하나의 프로세스에서 복제되어 나온 자식들이다.

 

이때, 프로세스를 복제하여 자식 프로세스를 낳는 과정을 알아보자.

 

 

 

1. Create Process

 

앞서 말했듯이 모든 프로세스들은 복제되어 생성된다.

 

그리고, 기존 프로세스에서 새로운 프로세스를 생성하는 시스템콜이 fork() 이다.

 

fork 는 현재 실행중인 프로세스와 똑같은 프로세스를 생성한다.

 

이때. 기존 프로세스를 parent process, 복사된 프로세스를 child process 라고 한다.

 

child process는 parent process 의 주소공간(메모리)을 복사하여 만들어진다.

 

즉, 두 프로세스는 같은것을 공유하는 것이 아니라, 아예 새로 복사되어 생성된다.

 

여기서 복사된다는 것은, 프로세스에는 code, data, heap, stak등의 데이터들이 존재하는데,

 

이 데이터들이 똑같이 복사된다는 개념이다.

 

또한 fork의 리턴값은, parent의 경우 child의 pid를 리턴하고 child의 경우 0을 리턴한다.

 

아래 예제를 보며 생각해보자.

 

fork process

 

위의 그림은 A라는 프로세스가 fork를 통해 B라는 프로세스를 생성한 것이다.

 

이 때, A의 fork 시스템콜의 리턴값은 child의 pid이므로 101이고,

 

B의 fork 시스템콜의 리턴값은 0이다.

 

 

이제 fork()라는 시스템콜에 대하여 기본 개념을 알았으니 실제 코드에 적용해보자.

 

아래 코드를 살펴보자.

 

fork() codes in ubuntu

 

위의 코드를 컴파일하여 실행시키면 어떤 결과가 발생할까?

 

우선 첫번째 fork()가 수행되는동안 원래 실행되던 프로세스가 자신과 똑같은 프로세스를 생성한다. (총 2개)

 

두번째 fork()가 수행되면, 실행중인 두개의 프로세스가 각자 자신과 같은 프로세스를 생성한다. (총 4개)

 

세번째 fork()가 수행되면, 실행중인 네개의 프로세스가 각자 자신과 같은 프로세스를 생성한다. (총 8개)

 

fork() 세번한 프로세스

 

위의 그림처럼 세번 fork를 하면 총 8개의 프로세스가 생성되는 것이다.

 

 

 

2. Replace Process

 

앞서 fork를 통해 새로운 프로세스를 생성했다면,

 

실행되는 중에 다른 형태의 프로세스로 변하고 싶을 때 사용하는 시스템콜도 있다.

 

exec( ) 라는 시스템 콜이 그 역할을 해준다.

 

exec 시스템콜은 현재 실행중인 프로세스의 메모리를 싹 비워주고 처음부터 다시 시작하게 해준다.

 

즉, 만약 내가 현재 실행중인 프로세스와 완전 새로운 프로세스를 생성하고 싶다면

 

현재 실행중인 프로세스를 fork해주고 fork된 프로세스를 exec 를 통해 다른 형태로 만들어 주면 된다.

 

윈도우의 WIN32는 CreateProcess 라는 시스템콜로 한번에 처리가능하지만

 

유닉스의 POSIX 은 fork와 exec를 따로 처리해줘야한다.

 

exec 시스템콜은 뒤에 variant 들이 붙을 수 있는데  l, v, p, e 등의 variant가 붙을 수 있다.

 

이 variants 에 대한 자세한 사항을 알고싶다면 구글링을 해보자...

 

 

 

 

3. Process Termination

 

프로세스가 다 실행되고 종료할 때 exit( )라는 시스템 콜을 사용한다.

 

이때, 운영체제는 프로세스가 종료된다는것을 시스템콜로 인지하고,

 

그 프로세스를 정리한다 (그 프로세스가 썼던 메모리나 파일 열어봤던것들 정리)

 

그리고 나서 종료된 프로세스의 부모에게 리턴값을 전달해준다.

 

이때, 부모는 wait( ) 라는 시스템콜로 자기의 child 프로세스가 종료될 때를 감지하고 있는다.

 

참고로, wait는 자식마다 지정하는 것이 아니라, 자식들 중 아무나 종료되면 그 리턴값을 받는다.

 

예를들어 A라는 parent process가 wait로 기다리는 중일 때,

 

child process 가 10개라면, 그 중에서 가장 빨리 종료되는 프로세스의 리턴값을 받는것이다.

 

그래서 리턴값을 받기 전까지는 wait 시스템콜은 어느 프로세스가 리턴값을 줄지 모른다.

 

자식이 죽으면 부모가 리턴값을 넘겨받아야하는데, 만약 부모가 wait로 자식의 리턴값을 받지 않고있으면,

 

자식프로세스가 남긴 리턴값은 어디로 가지 못하고 떠돌게 된다.

 

이때, 이 애매하게 남겨진 자식 프로세스를 Zombie process 라고 한다.

 

또한, 부모 프로세스가 자신의 자식 프로세스의 리턴값을 받기 전에 종료된 경우

 

자식프로세스는 리턴값을 줄 부모 프로세스가 없어지게되고, 이런 프로세스를 Orphan process라고 한다.

 

이 경우에는 cascading termination(어떤 프로세스가 종료될 때 자식까지 종료시키는것)이나

 

reparenting으로 다른 부모를 설정해준다.

 

이 때, 주로 init process(root process)에게 입양해주고 init process는 주기적으로 

 

wait을 불러주면, 자식 프로세스가 리턴값을 잘 넘겨줄 수 있게 된다. 

 

 

exit 외에도 시그널을 날려서 프로세스를 종료시키는 kill 시스템콜,

 

parent까지 같이 종료시키는 abort 시스템콜 등이 있다.

 

 

 

4. process control block

 

모든 프로세스들은 각각 PCB(process control block)을 가지고 있다.

 

이 블록에는 프로세스에 관한 모든 정보들이 담겨져있다.

 

가령, process state, PID, PC, registers, scheduling information 등의 정보 말이다.

 

 

 

오늘 내용을 정리해보면

 

1. 프로세스를 생성할때는 fork( ) 시스템콜을 이용한다

 

2. 프로세스를 다른 형태로 전환하고싶을떄는 exec( ) 시스템콜을 이용한다.

 

3. 프로세스는 종료될 때 exit( ) kill( ) abort( ) 등의 시스템콜을 이용한다.

 

4. 프로세스가 종료될 때 그 리턴값을 부모프로세스에게 넘겨준다. 이때 부모는 wait( ) 시스템콜로 받을 준비를 하고 있어야 한다.

 

5. process control block는 프로세스에 대한 정보를 담고있다.

 

 

본 내용은 공부하며 정리한 것으로, 오류가 있을 수 있습니다.

'운영체제' 카테고리의 다른 글

IPC_2 (signals, RPCs, pipe)  (0) 2020.04.14
IPC_1 (cooperating process model)  (0) 2020.04.12
프로세스의 개념  (0) 2020.04.08
운영체제의 구조 (2)  (0) 2020.04.07
운영체제의 구조 (BIOS, Policy & Mechanism)  (0) 2020.04.05