Whenever a child process is terminated, the kernel will send one asynchronous signal to the parent process. The parent process can choose to :
1) ignore the signal
2) provide the signal handler
By calling wait, waitpid, the parent process can:
1) block if all of its child processes are still running
2) return immediately with the termination status of the child, if a child has terminated and is waiting for its termination status to be fetched.
3) return immediately with the error, if the parent process doesn't have any child processes.
Definition:
ubuntu@ip-172-31-23-227:~$ less /usr/include/x86_64-linux-gnu/sys/wait.h
......
# define WEXITSTATUS(status) __WEXITSTATUS (__WAIT_INT (status))
# define WTERMSIG(status) __WTERMSIG (__WAIT_INT (status))
# define WSTOPSIG(status) __WSTOPSIG (__WAIT_INT (status))
# define WIFEXITED(status) __WIFEXITED (__WAIT_INT (status))
# define WIFSIGNALED(status) __WIFSIGNALED (__WAIT_INT (status))
# define WIFSTOPPED(status) __WIFSTOPPED (__WAIT_INT (status))
# ifdef __WIFCONTINUED
# define WIFCONTINUED(status) __WIFCONTINUED (__WAIT_INT (status))
# endif
......
#ifdef __USE_BSD
# define WCOREFLAG __WCOREFLAG
# define WCOREDUMP(status) __WCOREDUMP (__WAIT_INT (status))
# define W_EXITCODE(ret, sig) __W_EXITCODE (ret, sig)
# define W_STOPCODE(sig) __W_STOPCODE (sig)
#endif
/* Wait for a child to die. When one does, put its status in *STAT_LOC
and return its process ID. For errors, return (pid_t) -1.
This function is a cancellation point and therefore not marked with
__THROW. */
extern __pid_t wait (__WAIT_STATUS __stat_loc);
......
/* Wait for a child matching PID to die.
If PID is greater than 0, match any process whose process ID is PID.
If PID is (pid_t) -1, match any process.
If PID is (pid_t) 0, match any process with the
same process group as the current process.
If PID is less than -1, match any process whose
process group is the absolute value of PID.
If the WNOHANG bit is set in OPTIONS, and that child
is not already dead, return (pid_t) 0. If successful,
return PID and store the dead child's status in STAT_LOC.
Return (pid_t) -1 for errors. If the WUNTRACED bit is
set in OPTIONS, return status for stopped children; otherwise don't.
This function is a cancellation point and therefore not marked with
__THROW. */
extern __pid_t waitpid (__pid_t __pid, int *__stat_loc, int __options);
......
2. wait example
proc.c:
#include<stdio.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<unistd.h>
void pr_exit(int status)
{
if(WIFEXITED(status)) {
printf("normal termination: exit status = %d\n", WEXITSTATUS(status));
}
else if(WIFSIGNALED(status)) {
printf("abnormal termination: exit status = %d%s\n",
WTERMSIG(status), WCOREDUMP(status)? "(core file generated)" : "");
}
else if (WIFSTOPPED(status)) {
printf("child stopped, signal number = %d\n", WSTOPSIG(status));
}
}
int main(int argc, char* argv[])
{
pid_t pid;
int status;
// Launch the first child
if((pid = fork()) < 0) {
printf("fork error!\n");
exit(1);
}
else if (pid == 0)
exit(7);
// Fetch the termination status of first child
if(wait(&status) != pid) {
printf("wait error!\n");
exit(2);
}
pr_exit(status);
// Launch the second child
if((pid = fork()) < 0) {
printf("fork error!\n");
exit(1);
}
else if(pid == 0)
abort(); // Generate the SIGABRT
// Fetch the termination status of the second child
if(wait(&status) != pid) {
printf("wait error!\n");
exit(2);
}
pr_exit(status);
// Launch the third child
if((pid = fork()) < 0) {
printf("fork error!\n");
exit(1);
}
else if(pid == 0)
status /= 0; // Generate the SIGFPE
// Fetch the termination status of third child
if(wait(&status) != pid) {
printf("wait error!\n");
exit(2);
}
pr_exit(status);
exit(0);
}
shell:
ubuntu@ip-172-31-23-227:~$ ./proc.out
normal termination: exit status = 7
abnormal termination: exit status = 6(core file generated)
abnormal termination: exit status = 8(core file generated)
3. waitpid example:
waitflags definition:
ubuntu@ip-172-31-23-227:~$ less /usr/include/x86_64-linux-gnu/bits/waitflags.h
......
/* Bits in the third argument to `waitpid'. */
#define WNOHANG 1 /* Don't block waiting. */
#define WUNTRACED 2 /* Report status of stopped children. */
......
proc.c:
#include<stdio.h>
#include<stdlib.h>
#include<sys/wait.h>
int main(int argc, char* argv[])
{
pid_t pid;
if((pid = fork()) < 0) {
printf("fork error!\n");
exit(1);
}
else if (pid == 0) {
/* first child process */
if ((pid = fork()) < 0) {
printf("fork error!\n");
exit(1);
}
else if (pid > 0) {
sleep(1);
printf("first child output!\n");
exit(0); // exit from first child process
}
// 2nd child process sleep for 2 seconds to let 1st
// child process exit, at this time, its parent process
// becomes "init" (process id: 1)
sleep(2);
printf("second child, parent pid = %d\n", getppid());
exit(0);
}
// Original Process: Wait for process id of first child
// Since first child will sleep for 1 second, and we don't setup
// WNOHANG flag as 3rd argument, so it will just block here to wait
// for first child
printf("before waitpid:\n");
if(waitpid(pid, NULL, 0) != pid) {
printf("waitpid error!\n");
exit(2);
}
printf("after waitpid:\n");
exit(0);
}
shell:
ubuntu@ip-172-31-23-227:~$ ./proc.out
before waitpid:
first child output!
after waitpid:
ubuntu@ip-172-31-23-227:~$ second child, parent pid = 1
No comments:
Post a Comment