pid_t fork(void)
파라미터
* 없음
반환값
* 성공: 부모 프로세스 -> 자식 프로세스의 PID값, 자식 프로세스 -> 0
* 실패: 부모 프로세스 -> -1, 자식 프로세스 -> 생성되지 않음.
-> fork의 경우 자식 프로세스를 생성할 떄 모든 데이터를 복제하여 생성한다.
pid_t getpid(void);
pid_t getppid(void);
파라미터
* 없음
반환값
* getpid: 현재 프로세스의 PID
* getppid: 현재 프로세스의 부모 프로세스 PID
exec 함수의 경우 fork에서 생성된 데이터를 지우고 실행한 명령어의 새로운 데이터로 구성한다.
int execl(const char *path, const char *arg, .../* (char *) NULL */);
int execlp(const char *file, const char *arg, ... /* (char *) NULL */);
int execle(const char *path, const char *arg, ... /*, (char *) NULL, char * const envp[] */);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);
void exit(int status);
파라미터
* status: exit status
* 성공: 0
* 실패: None Zero
pid_t wait(int *wstatus);
파라미터
- wstatus: child process의 종료 상태
반환값
- 성공시 : terminated 된 자식 프로세스의 pid
- 실패시 : -1
======================================
사용 가능 메크로
WIFEXITED(wstatus) : 0이 아닌 값을 리턴하면 자식프로세스가 정상종료했다는 의미.
WEXITSTATUS(wstatus) : 정상 종료했음을 확인하면 해당 메크로를 통해여 종료 코드를 확인할 수 있다.
WIFSIGNALED(wstatus) : 이 매크로가 참이면 Signal을 통해 프로세스가 비정상 종료 했다는 뜻
WTERMSIG(wstatus) : SIFSIGNALED(status)매크로가 참일 경우 자식 프로세스를 종료시킨 시그널 번호를 얻는 매크로
WCOREDUMP(wstatus) : 시스템에 따라서는 WIFSIGNALED(status)가 참일 경우 자식 프로세스가 core덤프 파일을 생성했는지를 확인하는 이 매크로를 제공
WIFSTOPPED(wstatus) : 이 매크로가 참이면 자식 프로세스는 현재 멈춰있는(stopped) 상태이다.
WSTOPSIG(wstatus) : WIFSTOPPED(status)매크로가 참일 경우 자식 프로세스를 멈춤상태로 만든 시그널번호를 얻는다.
pid_t waitpid(pid_t pid, int *status, int options);
파라미터
- pid: 종료 대기할 프로세스의 pid
- status: 자식 프로세스의 종료 코드
- options
- WNOHANG. : waitpid를 실행했을 떄, 자식 프로세스가 종료되어 있지 않으면, 블록상태가 되지 않고 바로 리턴하게 해준다.
- WUNTRACED : pid에 해당하는 자식 프로세스가 멈춤 상태일 경우 그 상태를 리턴한다.
- WCONTINUED : 중단 되었다가 재개된 자식 프로세스의 상태를 받는다.
반환값
- 양수: 상태가 바뀐 child process의 pid
- 0: WNOHANG 지정시
- -1:실패
pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage);
파라미터
- pid: 종료 대기할 프로세스의 pid
- status: 자식 프로세스의 종료 코드
- options
- WNOHANG. : 자식 프로세스가 종료되어 있지 않으면, 블록상태가 되지 않고 바로 리턴하게 해준다.
- WUNTRACED : pid에 해당하는 자식 프로세스가 멈춤 상태일 경우 그 상태를 리턴한다.
- WCONTINUED : 중단 되었다가 재개된 자식 프로세스의 상태를 받는다.
- rusage: 리소스 사용량
반환값
- 양수: 상태가 바뀐 child process의 pid
- 0: WNOHANG 지정시
- -1:실패
struct rusage {
struct timeval ru_utime; /* user CPU time used */
struct timeval ru_stime; /* system CPU time used */
long ru_maxrss; /* maximum resident set size */
long ru_ixrss; /* integral shared memory size */
long ru_idrss; /* integral unshared data size */
long ru_isrss; /* integral unshared stack size */
long ru_minflt; /* page reclaims (soft page faults) */
long ru_majflt; /* page faults (hard page faults) */
long ru_nswap; /* swaps */
long ru_inblock; /* block input operations */
long ru_oublock; /* block output operations */
long ru_msgsnd; /* IPC messages sent */
long ru_msgrcv; /* IPC messages received */
long ru_nsignals; /* signals received */
long ru_nvcsw; /* voluntary context switches */
long ru_nivcsw; /* involuntary context switches */
};
struct timeval {
long tv_sec;
long tv_usec;
}
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/time.h>
#include<sys/wait.h>
#include<sys/resource.h>
#define TEST_PATH "./"
#define AUTHER "Yoon Yeoung Jin "
#define USE_WAIT 0
#define USE_WAIT4 1
void yj_print_pid(void)
{
pid_t pid;
pid = getpid();
printf(" * current process pid : %d\n", pid);
}
void yj_print_ppid(void)
{
pid_t pid;
pid = getppid();
printf(" * parent process pid : %d\n", pid);
}
void yj_print_ruseage(const char *leader, const struct rusage *ru)
{
const char *ldr = (leader == NULL) ? "" : leader;
printf("%sCPU time (secs): user=%.3f; system=%.3f\n", ldr,
ru->ru_utime.tv_sec + ru->ru_utime.tv_usec / 1000000.0,
ru->ru_stime.tv_sec + ru->ru_stime.tv_usec / 1000000.0);
printf("%sMax resident set size: %ld\n", ldr, ru->ru_maxrss);
printf("%sIntegral shared memory: %ld\n", ldr, ru->ru_ixrss);
printf("%sIntegral unshared data: %ld\n", ldr, ru->ru_idrss);
printf("%sIntegral unshared stack: %ld\n", ldr, ru->ru_isrss);
printf("%sPage reclaims: %ld\n", ldr, ru->ru_minflt);
printf("%sPage faults: %ld\n", ldr, ru->ru_majflt);
printf("%sSwaps: %ld\n", ldr, ru->ru_nswap);
printf("%sBlock I/Os: input=%ld; output=%ld\n",
ldr, ru->ru_inblock, ru->ru_oublock);
printf("%sSignals received: %ld\n", ldr, ru->ru_nsignals);
printf("%sIPC messages: sent=%ld; received=%ld\n",
ldr, ru->ru_msgsnd, ru->ru_msgrcv);
printf("%sContext switches: voluntary=%ld; "
"involuntary=%ld\n", ldr, ru->ru_nvcsw, ru->ru_nivcsw);
}
int main(int argc, char **argv)
{
int wstatus = 0;
pid_t child_pid = 0;
pid_t current_pid = 0;
struct rusage usage;
current_pid = fork();
if(current_pid == -1){
printf("fork() fail : %s\n", strerror(errno));
return -1;
} else if(current_pid > 0){
/* parent process */
printf(" [*] THIS IS PARENT PROCESS\n");
yj_print_pid();
} else {
/* child process */
printf(" [*] THIS IS CHILD PROCESS\n");
yj_print_pid();
yj_print_ppid();
sleep(1);
if(execl("/bin/ls", "ls", "-al", TEST_PATH, NULL) == -1){
printf("execl() fail : %s\n", strerror(errno));
exit(-1);
}
}
#if USE_WAIT
child_pid = wait(&wstatus);
if(child_pid == -1){
printf("wait() fail: %s\n", strerror(errno));
return -1;
}
if(WIFEXITED(wstatus)){
printf(" * The child process(%d) terminated successfully. (CODE: %d)\n ", child_pid, WEXITSTATUS(wstatus));
} else {
printf(" * The child process(%d) is not exited\n ", child_pid);
}
#elif USE_WAIT4
child_pid = wait4(current_pid, &wstatus, 0, &usage);
if(child_pid == -1){
printf("wait4() fail: %s\n", strerror(errno));
return -1;
}
if(WIFEXITED(wstatus)){
printf(" * The child process(%d) terminated successfully. (CODE: %d)\n ", child_pid, WEXITSTATUS(wstatus));
yj_print_ruseage(AUTHER, (const struct rusage *)&usage);
} else {
printf(" * The child process(%d) is not exited\n ", child_pid);
}
#endif
return 0;
}