-
임시 - Linux Kernel - 3장 : System Call(2) ( 고건 교수님 OLC 강의 )Linux Kernel 2024. 7. 1. 20:06
3장 - system call ( 2 )
fork()는 parent를 그대로 복사한다.
- PCB, 이미지 모두 그대로 복사한다.
exec()은 복사한 상태 위에서 overwrite를 하는 것이다.
wait ( 2 ) system call
(커널은 메모리의 어느 영역이든 접근할 수 있다는 점을 기억하자!)
어떤 프로세스가 wait 함수를 호출하면
커널이 해당 프로세스를 block한다. ( = cpu를 빼앗는다.(preemptive) )
이후 커널은 ready 리스트에서 우선순위가 높은 프로세스의 PCB를 바탕으로
pc(program counter)값을 찾아 그리로 jump한다. ( cpu를 할당해준다. )
아래 코드에서는 parent는 wait 함수를 호출했는데,
이는 child가 끝날 때까지 기다렸다가 신호가 오면 ready 상태로 옮기게 된다.
#include <unistd.h> #include <stdio.h> #include <sys/wait.h> int main() { int pid; pid = fork(); if(pid == 0){ printf("I am child\n"); sleep(2); execlp("/bin/date", "/bin/date", (char*)0); } else{ printf("I am parent\n"); wait(&pid); printf("finish! \n"); } return 0; }child의 차례가 되어서 cpu가 할당되게 되면, exec을 하면서 새 프로그램으로 덮여쓰여지게 된다. ( date라는 프로그램의 main으로 시작되게 됨. )
child는 본인 작업이 끝나면, os에게 작업이 끝났다고 알린다.
OS는 child에게서 받은 부모 정보를 토대로 parent를 block 상태에서 ready 상태로 옮긴다.
exit(2) system call
execlp("/bin/date", "/bin/date", (char*) 0);위 코드에서 date 프로그램이 디스크에서 자식 프로세스에게 덮어쓰여지고,
프로그램이 실행될 때, “덮여쓰여진 main” 부터 시작되게 되는데,
main 문이 끝날 때의 ‘}’ 괄호를 컴파일러가 알아서 exit 시스템 콜로 바꿔준다.
바꿔 말하면, 위 date 프로그램이 끝나면 runtime에 exit 시스템 콜 때문에
trap에 걸려서 커널로 진입하게 된다.
다시 말하면, 이 시스템 콜로 인해 자식 프로세스는 부모 프로세스에게 자신이 끝났음을 알릴 수 있게 된 것이다. ( 자식 프로세스 → 커널 → 부모 프로세스 )
정리하면,
프로세스를 위한 시스템 콜에는 다음과 같이 존재한다.
- fork - child를 복사해서 만들어줌. parent와 PCB, image 일치.
- exec - 새로운 image를 덮어 쓴다. 이후 main function으로 간다.
- wait - 자식 프로세스가 종료될 때까지, 호출한 프로세스를 sleep
- exit - 가지고있는 모든 자원을 반납하고, 부모에게 종료됨을 알린다.
컨텍스트 스위치를 할 때,
cpu 정보를 커널이 가지고 있는 프로세스의 PCB에 저장해놓고,
다시 ready 리스트에서 우선순위 높은 프로세스의 PCB가 가지고 있는 cpu 정보를 cpu에 넣어준다.
커널 안에는 컨텍스트 스위치를 도와주는 schedule( )이라는 함수가 있다.
internal 한 function으로 a.out에 알려지지 않는 function이다.
( → 커널 밖에서는 부를 수 없다는 뜻이다. )
schedule( ) 함수는
다음에 run할 프로세스를 고르고, context_switch()를 호출한다.
( → schedule 함수는 read( ), wait( ), exit( ) 등의 함수들이 호출한다. )
context_switch( ) 함수가 호출되면,
- 현재 CPU 상태 정보를 물러나는 process의 PCB에 넣어주고,
- PCB에 SLEEP 상태임을 표시해주고 나서,
- 새로 선정한 process의 PCB에서 cpu 상태 정보를 CPU 레지스터로 load 해준다.
이후, PC 값을 보고 다시 fetch하기 시작하면, context switch가 다 이루어지게 된 것이다.
총정리

- 먼저 sh에서 fork함수를 호출해주면,
- fork( ) 함수를 토대로, child의 PCB와 image를 만들어 놓고 ready list에 둔다.
- fork가 리턴되면, (이 경우 부모가 먼저 리턴되었음을 가정)
- wait( ) 함수를 호출하게 되고
- wait ( ) 함수는 자신을 호출한 프로세스를 자식프로세스가 종료될 때까지 sleep 시키며,
- 자식 프로세스가 ready list에서 본인의 차례가 되어 cpu를 할당받으면, pc에 저장되어 있는 값은 부모의 pc값과 동일하게 시작되므로 PID = fork( ); 문으로 가게 되고,
- 이때, fork( )에서 리턴 받은 값은 0이므로 exec( )을 호출하게 된다.
- exec( )을 호출하면 디스크에서 “ls” 파일을 찾아오게 되고,
- 이를 자식 프로세스에 overlay (덮어씌워주기) 해준다.
- 이제 exec에서 pc가 자식 프로세스의 main으로 넘어가면서
- ls에 대해 fetch 후 실행 해주고
- main 문이 끝나면, exit 함수를 호출해준다. (자식 프로세스가 해야 할 작업이 끝남. )
- exit함수는 context_switch함수를 호출해주고,
- 부모 프로세스는 자기 차례가 되면, wait( ) 함수에서 자식 프로세스가 종료되었음을 알게 되면서 해당 과정이 끝나게 된다.
프로세스 context를 이루는 요소들.
user space에는 text/ data/ bss / heap/ stack 으로 이루어져 있다.
- text : 코드 ( instruction )
- data : 초기화된 전역 변수 ⇒ 컴파일 할 때, 공간이 할당됨.
- bss : 초기화되지 않은 전역 변수 ⇒
kernel space에는 pcb/ stack 으로 이루어져 있다.
하드웨어적으로는, state vector ( PC, SP, flags, reg0, … )이 있다.
“Daemon” or “Server” 프로세스
서버는 근본적으로 a.out이다.
a.out은 booting time에 올라오게 되고,
대부분의 시간을 sleep하고 있다가
request가 오면 서비스 해주고, 다시 sleep한다.
httpd - 웹 서버
ftpd - ftp 서버 로 알고 있으면 된다.
'Linux Kernel' 카테고리의 다른 글
임시 - Linux Kernel - 4장 : Process management( 1 ) ( 고건 교수님 OLC 강의 ) (0) 2024.07.04 커널 모듈 개발의 기초 - Linux 커널 모듈 프로그래밍 가이드(5.x) 참고 (4) 2024.07.02 임시 - Linux Kernel - 2장 (2) : Process Management ( 고건 교수님 OLC 강의 ) (2) 2024.06.30 임시 - Linux Kernel - 2장 (1) : System Call (1) ( 고건 교수님 OLC 강의 ) (0) 2024.06.30 임시 - Linux Kernel - Introduction ( 고건 교수님 OLC 강의 ) (0) 2024.06.29