티스토리 뷰
☞ fork, getpid, getppid, waitpid, wait, setsid, getsid, getpgrp, getpgid, setpgid, setpgrp
<sys/types.h>
<unistd.h>
<sys/wait.h>
pid_t fork(void);
pid_t getpid(void);
pid_t getppid(void);
pid_t waitpid(pid_t pid, int *status, int options);
pid_t wait(int *status);
pid_t setsid(void);
pid_t getsid(pid_t pid);
pid_t getpgrp(void);
int getpgid(pid_t pid);
int setpgid(pid_t pid, pid_t pgid);
각 프로세스는 pid_t 타입의 고유한 프로세스 아이디(PID)를 갖습니다. getpid()를 통해서 자신의 PID를 조회할 수 있고 getppid()로 자신의 부모 프로세스의 아이디를 조회할 수 있습니다. 실행중인 프로세스에서 다른 프로그램을 실행시키는 과정을 살펴보면 그 시작은 fork()를 통해서 자식 프로세스를 생성하는 것으로 시작합니다. fork()는 기존 프로세스와 동일한 복사본을 새롭게 만들고 새로운 프로세스 ID를 부여합니다. 이 시점부터 부모 프로세스와 자식 프로세스는 각각 독립적으로 동시 수행됩니다. 자식 프로세스는 종료 시점에 부모 프로세스로 시그널을 전송하는 것으로 그 생애를 마감합니다. 부모 프로세스가 자식 프로세스의 실행이 종료 될 때 까지 실행을 잠시 멈추고 싶다면 wait() 또는 waitpid()를 호출하면 됩니다. 상태 정보를 받을 정수 변수의 포인터를 인수로 wait() 또는 waitpid()를 호출하면 자식 프로세스의 종료를 기다렸다가 상태를 정보를 담아 리턴합니다. 리턴값은 상태 정보를 확인한 자식 프로세스의 PID 입니다. wait()는 waitpid()를 waitpid (-1, &status, 0)로 단순화한 형태입니다. waitpid()에서 pid가 양수값이면 특정 자식 프로세스를 대상으로 하지만 pid를 -1로 전달하면 모든 자식 프로세스를 대상으로 하고 0으로 전달하면 동일한 프로세스 그룹에 속한 자식 프로세스들을 대상으로 하고 -1보다 작은 음수 값은 -pgid의 의미로 프로세스의 그룹 아이디가 pgid인 자식 프로세스를 대상으로 합니다. options에는 WNOHANG과 WUNTRACED를 OR로 지정할 수 있는데 WNOHANG는 기다리지 않도록 하고(종료된 자식 프로세스가 없으면 0 리턴) WUNTRACED는 멈춘 프로세스 뿐만아니라 종료된 자식 프로세스에 대해서도 정보를 리턴합니다.
☞ 예제1
static int proc_execute_internal(const char * file, const char * args[], bool wait_child, bool close_output, bool close_err, bool hide_cmd_args, int * out_pid)
{
pid_t pid,
tmp;
char executable_path[PATH_MAX];
if (out_pid) {
* out_pid = 0;
}
(void)envvar_bindir_file(executable_path, PATH_MAX, file); /* do not process SIGCHLD, a child process will be defunct */ if (wait_child) {
signal(SIGCHLD, SIG_DFL);
} else {
signal(SIGCHLD, SIG_IGN);
}
pid = fork();
if (pid == -1) {
perror("fork");
return ER_GENERIC_ERROR;
} else if (pid == 0) { /* a child process handle SIGCHLD to SIG_DFL */ signal(SIGCHLD, SIG_DFL);
if (close_output) {
fclose(stdout);
}
if (close_err) {
fclose(stderr);
}
if (execv(executable_path, (char * const * )args) == -1) {
perror("execv");
return ER_GENERIC_ERROR;
}
} else {
int status = 0;
if (hide_cmd_args == true) {
hide_cmd_line_args((char ** )args);
}
if (wait_child) {
do {
tmp = waitpid(-1, & status, 0);
if (tmp == -1) {
perror("waitpid");
return ER_GENERIC_ERROR;
}
} while (tmp != pid);
} else {
if (out_pid) {
* out_pid = pid;
}
return NO_ERROR;
}
if (WIFEXITED(status)) {
return WEXITSTATUS(status);
}
}
return ER_GENERIC_ERROR;
}
위의 예제 코드는 큐브리드 DBMS의 코드 일부로 fork() 리턴 값이 0인 자식 프로세스에서는 execv()를 호출하지만 양수를 리턴한 부모 프로세스에서는 자식 프로세스의 종료를 기다리는 waitpid()를 호출하는 것을 참조 할 수 있습니다.
setsid()는 현재 프로세스의 PID로 프로세스 그룹 아이디를 만들고 새로운 세션을 만들면서 현재의 프로세스를 그룹의 세션 리더로 설정합니다.
getsid()는 pid로 지정한 프로세스의 세션 리더의 그룹 아이디를 리턴합니다. pid를 0으로 지정하면 현재 프로세스를 의미합니다.
getpgrp()는 현재 프로세스의 프로세스 그룹 아이디를 조회합니다.
getpgid()는 pid 프로세스의 프로세스 그룹 아이디를 조회합니다. pid를 0으로 지정하면 현재 프로세스를 의미합니다.
setpgid()는 pid 프로세스의 프로세스 그룹 아이디를 설정합니다. pid를 0으로 지정하면 현재 프로세스를 의미합니다.
'C | C++' 카테고리의 다른 글
사전 클래스(std::map) 정리 (0) | 2024.01.22 |
---|---|
벡터 클래스(std::vector) 정리 (0) | 2024.01.22 |
프로그램 실행 (0) | 2018.08.04 |
프로그램 종료 (0) | 2018.08.04 |
환경 변수 다루기 (0) | 2018.08.04 |