본문 바로가기
대딩/운영체제

시스템콜_fork(), exec(), exit()

by 경아ㅏ 2022. 5. 11.

System Call

개발자 입장에서 Process를 control 할 수 있는 도구로, 사용자 application에서 운영체제에게 특정 동작을 요청하는 역할을 수행합니다.

본 포스팅에서는 여러가지 시스템콜 중에서 Process의 생성, 실행, 종료와 관련된 시스템콜들을 다룹니다. 

 

 

int fork()

fork()는 부모 프로세스와 동일한 자식 프로세스를 생성하는 시스템콜입니다.

fork()가 수행되면, 새로운 PCB와 Process address space를 만들고 초기화합니다. 이후, 부모 프로세스의 Process address space 상태를 자식 프로세스에게 그대로 복사합니다. 부모 프로세스가 사용하고 있던 커널에 의해 할당된 리소스들(ex I/O, 파일)에 대한 정보도 자식 프로세스에 그대로 복사합니다.

이렇게 되면, fork()함수를 통해 부모 프로세스와 동일한 자식프로세스 하나가 별도로 생성됩니다. 새로 생성된 프로세스는 ready queue에 들어가 별도의 PID를 갖고 스케줄링 됩니다. 

 

fork() 함수의 리턴 값을 보면 int 정수를 리턴하는 것을 알 수 있습니다. 

자식 프로세스는 0을 리턴하며, 부모 프로세스는 자식프로세스의 PID를 반환합니다.

 

 

따라서 위의 코드를 실행시키면 부모 프로세스와 동일한 자식 프로세스가 생성되고 두 프로세스가 실행됩니다. 자식 프로세스는 fork()의 리턴값이 0이므로  "Child of %d"로 시작하는 문장을, 부모 프로세스는 fork()의 리턴값이 자식 프로세스의 pid 값이므로 "I am %d"로 시작하는 문장을 출력합니다.

 

 

int exec(char* prog, char *argv[])

 

exec()은 fork()와 함께 사용되는 시스템 콜로, 프로세스에 새로운 프로그램을 덮어쓰는 함수입니다.

fork() 함수가 호출되면, 부모 프로세스는 자신과 동일한 자식 프로세스를 만듭니다. 이 때, 자식 프로세스에서 exec() 함수를 호출하면 prog 프로그램을 자식 프로세스의 Process address space(code segemnt)에 로드시켜 덮어씁니다. 새로운 프로그램을 위해 PCB의 문맥 정보들을 초기화 하고, 이를 Ready queue에 삽입합니다. 

 

주의할 것은 exec() 함수는 새로운 프로세스를 만드는 함수가 아니라는 것입니다. 새로운 프로세스는 fork()를 통해 만들고, exec()은 프로세스에 새로운 프로그램을 덮어씌우는 역할을 합니다.

 

쉘은 exec()을 호출하는 대표적인 프로그램입니다. 

쉘에서 명령어를 실행하는 과정을 생각해 보면 $_와 같이 커서가 깜빡거립니다. 이 때 명령어(실행할 프로그램의 이름)  ls -al을 입력하면 쉘 프로세스는 자식 프로세스를 만들고 exec() 함수로 ls-al 프로그램을 실행시켜 현재 디렉토리에 있는 파일 목록을 출력합니다.  쉘 프로세스는 wait(pid) 함수를 통해 자식 프로세스가 종료될 때까지 대기하고, 다음 명령어를 입력 받습니다.

 

 

프로세스 종료

 

정상 종료를 처리하는 시스템콜은 다음과 같습니다.

 

  • exit(): 프로세스가 종료되기 위해 필요한 사후처리를 모두 해주고 종료하는 함수입니다.
  • _exit(): 사후처리 없이 종료하는 함수입니다.

         

비정상적인 종료를 처리하는 시스템콜은 다음과 같습니다.

 

  • abort()
  • signal에 의한 종료(ex. kill pid)

 

wait()은 자식 프로세스의 종료를 기다리는 시스템콜입니다.

 

  • zombie process: 자식 프로세스가 종료 되었지만 부모 프로세스가 아직 wait()을 함수를 호출하지 않은 상태를 말합니다.
  • orphan process: 부모 프로세스가 wait() 함수를 호출하지 않고 종료한 경우를 말합니다.

 

댓글