프로세스 종료에 대해 알아보겠습니다.
1) exit() 시스템 콜
기본적으로 많이 사용되는 프로세스 종료 표준함수는 exit() 시스템 콜입니다.
exit 시스템 콜의 형태는 아래와 같습니다.
#include <stdlib.h> void exit(int status); | ||
입력 인자 | void | 없음 |
반환 값 | int | 프로세스의 종료 상태를 나타내기 위한 값 |
생각해보시면, exit() 시스템 콜이 호출되게 되면, 프로세스가 즉시 종료되기 때문에 반환 값이 있을 수가 없습니다. 그럼 프로세스가 정상적으로 종료되었는지 확인하는 방법은 무엇일까요??
바로 status 인자를 이용하여 프로세스의 종료 상태를 확인할 수 있습니다. 즉 status가 입력 인자이면서 반환 값 용도로 사용 되는 것이죠. status 인자는 셸 같은 다른 프로그램에서 확인이 가능합니다.
자세히 말씀드리면 status & 0377 값이 부모 프로세스에게 전달됩니다.
프로세스를 종료하는 다른 방법에 대해 알아보겠습니다.
솔직히 말씀드리면, 깔끔하게 프로그램이 모든 Logic을 수행하고 종료하는 것이 가장 깔끔하겠죠??
하지만, 항상 모든 것이 자신이 원하는 대로 되지는 않습니다. exit() 시스템 콜 외에 다른 종료법에 대해 알아봅시다. 여기서는 시그널이나 다른 방법 외에 프로세스 종료 시스템 콜에 대해서만 알아보겠습니다.
2) atexit() 시스템 콜
atexit() 시스템 콜은 exit()시스템 콜과는 다르게 바로 프로세스를 종료하지 않습니다.
이 시스템 콜은 해당 프로세스가 실제 모든 로직을 끝내고 종료될 때를 위한 시스템 콜입니다.
여러분들이 꼭 나는 프로그램이 종료되기 전에 이 함수가 호출되었으면 좋겠어!! 라고 느끼신 적 있으신가요? atexit() 시스템 콜은 프로세스가 종료 될 때 실행할 함수를 등록하기 위한 용도로 사용됩니다.
#include <stdlib.h> int atexit(void (*function)(void)); | ||
입력 인자 | void (*function)(void) | 프로그램 종료 전 실행 할 함수의 포인터 |
반환 값 | int | 프로세스의 종료 상태를 나타내기 위한 값 |
위의 입력인자를 자세히 보면, 입력인자도 void 이며, 반환 값도 void 입니다.
그 말은 여러분이 atexit() 시스템 콜로 등록할 수 있는 함수는 입력 인자도, 반환 값도 없는 함수여야 한다는 것 입니다.
예제 코드를 한번 보시죠,
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
void exit_child(void)
{
printf("Child is Die: %d ", getpid());
}
void exit_parent(void)
{
printf("Parent is Die : %d ", getpid());
}
int main()
{
pid_t pid;
pid = fork();
if(pid == -1)
{
perror("Error ");
exit(0);
}
if(pid == 0)
{
printf("I am Child : %d ", getpid());
atexit(exit_child);
}
else
{
printf("I am Parent : %d ", getpid());
atexit(exit_parent);
}
}
실행 결과를 보시죠,
위의 코드에서 부모 프로세스와 자식 프로세스는 각각 atexit()를 이용하여 프로그램이 종료되기 전
함수들을 호출하고 있습니다. 그 실행결과는 아래와 같구요, 조금 이해 되시나요?
atexit() 함수는 한 번이 아니라 여러번 사용할 수도 있습니다. 그럴 경우는 어떻게 될까요??
먼저 atexit()로 등록한 함수부터 순차적으로 호출될까요?? 아닙니다.!!
등록한 함수들은 스택에 저장됩니다. 스택 자료구조는 후입 선출(First In Last Out)이죠??
함수들은 등록한 순서의 역순으로 호출이 일어난다는 것 잊지 마세요.!!
이러한 프로세스 종료들은 여러 단계를 수행한 후 최종적으로는 _exit() 시스템 콜을 호출하여
프로세스를 종료하게 됩니다. 처음 프로세스를 종료하려 하면, atexit()를 이용하여 등록한 함수를 위에서 설명한 대로 등록 역순으로 호출하게 됩니다. 그리고 열어놓았던 파일들을 모두 스트림 버퍼를 비우게 되며 tmpfile()을 통해 생성한 임시파일들을 모두 삭제합니다. 위 과정을 거치게 되면 프로세스가 사용자 영역에서 프로세스를 종료하기 위한 준비는 완료되고, 최종적으로 _exit() 시스템 콜을 호출함으로써 커널 영역에서의 마무리 단계(리소스 해제) 후에 최종적으로 종료되죠.
이상 프로세스 종료에 대해 알아보았습니다. 다음에는 프로세스 대기에 대해 알아보겠습니다.
'Linux > System Programming' 카테고리의 다른 글
Warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings] (0) | 2016.01.12 |
---|---|
[프로세스][펌] Daemon Process (0) | 2015.12.09 |
리눅스 시스템 에러 - errno (0) | 2015.08.13 |
[프로세스 관리] 2. 새로운 프로세스 실행 (0) | 2015.04.14 |
[프로세스 관리] 1. 프로세스의 ID 얻기 (0) | 2015.04.12 |