8. Child Process 생성하기
컴퓨터를 부팅하면 제일 먼저 커널 프로세스가 로드된다. 그리고 이 커널은 터미널이 켜질때 마다 그에 해당하는 Shell, 즉 Child Process를 만든다. Shell은 사용자의 입력을 기다리고 입력이 들어오면 그에 따른 작업을 수행해주는 프로그램이다. 사용자가 Mail
이라고 입력하면 Mail
이라는 Child Process
가 생성 된다. 이처럼 프로세스들이 진행될 때는 자식 프로세스(Child Process)가 생성되면서 진행된다. 따라서 커널을 공부할 때 Child Process는 반드시 알아야하는 개념이다. 지금부터의 설명은 아래 그림과 함께 살펴보도록 한다.
# Note
잠시 여기서 프로그램과 프로세스의 차이에 대해 알아보자. 프로그램과 프로세스의 차이는 명확하다. 프로그램은 보조 기억 장치에서 실행이 되기만을 기다리는 정적인 데이터의 집합이고, 프로그램이 명령어와 데이터와 함께 메모리에 적재되면 프로세스가 되는 것 이다. 즉, 프로세스란 실행 중인 프로그램을 뜻한다.
1강에서 배웠듯 프로그램에는 User Stack
과 Kernel Stack
이 존재한다. User Stack
은 프로그램에서 function
을 사용할 때 사용된다. Kernel Stack
은 유저 모드에서 시스템 콜을 통해 커널의 function
들을 사용할 때 필요한 자료구조로 프로그램 실행에 필요한 Local Variable들을 저장하기 위한 공간이다. 만약 자료구조를 가변적인 Stack구조로 사용하지 않고 늘 공간을 확보해둔다면, 프로그램 크기가 엄청 커지고 운영 비용만 비싸질 것이다.
지금부터는 Child Process
를 생성하기 위한 과정들을 살펴볼 것이다. Child Process
생성을 위해서는 먼저 Process의 정보가 들어있는 PCB(Process Control Block)
를 만들고 그 PCB에 해당하는 Process를 만들어 줘야한다.
진행 순서는 아래와 같다.
- PCB 공간을 만들어 준다. 초기값으로 Parent Process의 PCB를 복사해온다. Parent가 사용하던 Resource(터미널, 키보드, 스크립트)를 자식 프로세스도 사용하게 되는 것이다.
Parent Process
의 실행 환경이Child Process
의 실행 환경이 된다. Child Process
가 들어갈 수 있는 메모리 공간을 확보하여 초기값을 지정한다. 이를 위해 커널은 Memory의 Data Structure에 가서 빈 메모리 공간을 찾아 공간을 지정해준다. 지정된 공간에 Child Process의 값들을 넣기 전에 먼저Parent Process
의 image를 똑같이 복사를 해준다. 이 이유는 후에 등장한다. 프로세스 처리과정을 간편화하기 위해 복사한다고 일단 기억해두자.- 디스크로부터
Child Process
에 새로운 image를 로드한다. - 새로 생긴
Child Process
의PCB
를 CPU의 ready queue에 등록하여 CPU를 사용 할 수 있게끔 준비해준다. (아직까지 CPU는Parent Process
가 사용 중 이기 때문이다.)
이러한 4가지 과정을 시스템 콜의 용어로 정리하면 두가지로 정리할 수 있는데,
- 1번과 2번의 과정을 Fork라고 부른다. (Parent와 동일한 것을 만든다.)
- 3번과 4번의 과정을 Exec이라고 부른다. (디스크로 부터 새 이미지를 읽어온다.)
8.1 Fork
일단 Fork(포크)에 대해 알아보기 전에 Fork는 한번 호출하면 두번 리턴한다라는 개념으로 기억하자. 지금은 이해가지 않더라도 일단 이 사실을 받아들이고 설명을 읽어보자.
두번의 리턴 중 첫번째 리턴은 Parent Process
가 본인이 가지고 있는 Process 상태를 그대로 Child Process
에 복사하고 CPU의 ready queue
에 Child Process
를 등록 시켜놓고 다시 Parent Process
로 리턴하는 과정이다.
# Note
단순히 함수를 호출한 후 리턴해서 그 다음 실행흐름으로 위치했다는 의미다. 프로그램적으로 너무나도 당연한 과정이다.
그 후 ready queue
에 등록되어 대기중이었던 Child Process
가 CPU를 점유하게 된다. Child Process
가 실행되는데, Child Process
는 만들어질 당시 Parent Process
와 동일한 PCB(Process Control Block)
즉, 같은 State Vector
를 가지고 생성되었기 때문에 Fork를 호출하고 난 바로 그 다음 진행 시점에서 실행된다.
즉 Child Process
는 Parent Process
가 가지고 있는 정보들 뿐만 아니라 프로그램 진행 상황까지 완전히 똑같은 상태를 가지게 되고 이런 현상 때문에 Child Process 또한 Fork에서 리턴하게 된다.
그렇기 때문에 한번 Fork를 해서 두번 돌아온다는 표현이 생긴 것 이다. 단, 운영체제가 이런 두 가지의 return으로 일어나는 혼동을 막기위해 리턴하는 값은 다르게 해준다. 지금까지 설명한 과정을 아래 그림과 함께 살펴보자.
Fork가 두번 리턴되는데 한번은 Parent Process
로, 한번은 Child Process
으로 리턴한다. 그리고 리턴할 때의 값은 pid 값이다. pid
는 Process Id라는 의미로 이는 유닉스 시스템에서 각 프로세스에게 할당하는 고유 식별값이다. pid
값이 0이라면 가면 Child Process
를 의미하고 그게 아니라면 현재 실행 중인 프로세스는 Parent Process
다.
# Note
fork()는 두 번 리턴하는데, 각 리턴값은 다음과 같다. Child Process에게는 0값을 리턴하고 Parent Process에게는 Child Process의 pid(process id)를 리턴한다.
아래의 프로그램을 리뷰하면서 내용을 정리해보자.
fork.c
라는 이름을 가진 소스파일이고, fork를 호출하는 프로그램이다. 프로그램의 출력 결과를 예상 해보고 확인하면서 지금까지 배운 fork
를 리뷰해본다.
fork()
를 호출하면 위 그림에 나와 있는 코드가 그대로 복사되어 Child Process
에게 할당된다. 하나 더 생성이 되는 것이다. 그럼 Parent Process
와 Child Process
는 서로 같은 코드와 상태를 가지고 있게 되는 것이다.
fork()
호출의 리턴값 pid
의 값에 따라 Child Process
가 실행되거나 Parent Process
가 실행된다. 결국엔 둘 다 실행되겠지만 둘 중 누가먼저 실행되는지 위 코드에서는 정확히 파악하기 어렵다. 보통은 부모 프로세스가 먼저 실행된다.
이번 강의에서는 System Call이 일어나는 절차에 대해 System Call Wrapper Routine, System Call Number 등을 배웠고 커널이 프로세스들과 하드웨어들을 관리하기 위해 정보를 모아둔 Data Structure인 metadata에 대해서 배웠다. 또 마지막으로 Child Process의 생성과정 중 Fork에 대해 간략히 알아보았다. 다음 3강에는 Fork를 좀 더 자세히 살펴보고 Exec에 대해 설명한다.
'임베디드 > [ Linux Kernel ]' 카테고리의 다른 글
[ Linux Kernel ] 08. Context Switch (0) | 2020.08.15 |
---|---|
[ Linux Kernel ] 07. 주요 시스템 콜 동작 원리 (0) | 2020.08.15 |
[ Linux Kernel ] 05. Process Management (0) | 2020.08.15 |
[ Linux Kernel ] 04. 시스템콜(System Call) (0) | 2020.08.15 |
[ Linux Kernel ] 03. 인터럽트와 트랩 (0) | 2020.08.15 |