标签:des c style class blog code
1. exit函数:
进程的五种正常的结束方式:
进程的三种非正常的结束方式:
不管进程如何终止,最后都会执行内核中的同一段代码:这段代码为进程关闭所有的相应的打开描述符,释放它所用的存储器等。
终止进程的父进程可以用wait和waitpid取得其终止状态。
对于父进程已经终止的进程,它们的父进程都被改为init进程,称这些进程被init进程领养。其操作过程如下:
在一个进程终止时,内核逐个检查所有活动进程,以判断它是否是正要终止进程的子进程,如果是,那么将该进程的父进程的id更改为1(init进程ID)。
这种进程保证了每个进程都有一个父进程。
另外一个问题是:如果子进程在父进程之前终止,那么父进程如何如何得到子进程的终止状态呢?
回答: 内核为每个终止进程保存了一定量的信息,所以当终止进程的父进程调用wait和waitpid,时可以得到这些信息。这些信息至少包括:进程ID,该进程的终止状态,
以及该进程使用CPU时间总量。在UNIX术语中,一个已经终止,但是其父进程尚未对其进行善后处理(终止进程的相关信息,释放它们仍然占用的资源)的进程被称为僵死进程。
上图是一个典型的UNIX/LINUX 进程状态模型。
2. wait 和 waitpid 函数:
当一个进程正常或异常终止的时候,内核就会向其父进程发送SIGCHLD信号。因为子进程的终止是个异步事件(可以在父进程运行的任何时候发生),所以这种信号也是内核向父进程发的异步通知。父进程有两种处理这个信号的方式: 1)忽略该信号; 2) 提供一个该信号发生时即被调用执行的函数(信号处理程序)。
调用wait或waitpid的进程可能会发生的情况:
下面是linux manpage 中对wait函数族的描述:
NAME wait, waitpid, waitid - wait for process to change state SYNOPSIS #include <sys/types.h> #include <sys/wait.h> pid_t wait(int *status); pid_t waitpid(pid_t pid, int *status, int options); int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options); /* This is the glibc and POSIX interface; see NOTES for information on the raw system call. */ Feature Test Macro Requirements for glibc (see feature_test_macros(7)): waitid(): _SVID_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED || /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200809L DESCRIPTION All of these system calls are used to wait for state changes in a child of the calling process, and obtain information about the child whose state has changed.(这些函数用来在调用进程中观察子进程状态的变化) A state change
is considered to be: the child ter‐minated (子进程终止); the child was stopped by a signal(子进程由于信号而停止); or the child was resumed by a signal(子进程因信号重新启动). In the case of a terminated child, performing a wait allows the system to release the resources associated with the child; if a wait is not performed, then the terminated child remains in a "zombie" state (see NOTES below). If a child has already changed state, then these calls return immedi‐ ately. Otherwise they block until either a child changes state or a signal handler interrupts the call (assuming that system calls are not automatically restarted using the SA_RESTART flag of sigaction(2)). In the remainder of this page, a child whose state has changed and which has not yet been waited upon by one of these system calls is termed waitable. wait() and waitpid() The wait() system call suspends execution of the calling process until one of its children terminates. The call wait(&status) is equivalent to: waitpid(-1, &status, 0); The waitpid() system call suspends execution of the calling process until a child specified by pid argument has changed state. By default, waitpid() waits only for terminated children, but this behavior is mod‐ ifiable via the options argument, as described below. The value of pid can be: < -1 meaning wait for any child process whose process group ID is equal to the absolute value of pid. -1 meaning wait for any child process. 0 meaning wait for any child process whose process group ID is equal to that of the calling process. > 0 meaning wait for the child whose process ID is equal to the value of pid. The value of options is an OR of zero or more of the following con‐ stants: WNOHANG return immediately if no child has exited. WUNTRACED also return if a child has stopped (but not traced via ptrace(2)). Status for traced children which have stopped is provided even if this option is not specified. WCONTINUED (since Linux 2.6.10) also return if a stopped child has been resumed by delivery of SIGCONT. (For Linux-only options, see below.) If status is not NULL, wait() and waitpid() store status information in the int to which it points. This integer can be inspected with the following macros (which take the integer itself as an argument, not a pointer to it, as is done in wait() and waitpid()!): WIFEXITED(status) returns true if the child terminated normally, that is, by call‐ ing exit(3) or _exit(2), or by returning from main(). WEXITSTATUS(status) returns the exit status of the child. This consists of the least significant 8 bits of the status argument that the child specified in a call to exit(3) or _exit(2) or as the argument for a return statement in main(). This macro should be employed only if WIFEXITED returned true. WIFSIGNALED(status) returns true if the child process was terminated by a signal. WTERMSIG(status) returns the number of the signal that caused the child process to terminate. This macro should be employed only if WIFSIGNALED returned true. WCOREDUMP(status) returns true if the child produced a core dump. This macro should be employed only if WIFSIGNALED returned true. This macro is not specified in POSIX.1-2001 and is not available on some UNIX implementations (e.g., AIX, SunOS). Only use this enclosed in #ifdef WCOREDUMP ... #endif. WIFSTOPPED(status) returns true if the child process was stopped by delivery of a signal; this is possible only if the call was done using WUN‐ TRACED or when the child is being traced (see ptrace(2)). WSTOPSIG(status) returns the number of the signal which caused the child to stop. This macro should be employed only if WIFSTOPPED returned true. WIFCONTINUED(status) (since Linux 2.6.10) returns true if the child process was resumed by delivery of SIGCONT. waitid() The waitid() system call (available since Linux 2.6.9) provides more precise control over which child state changes to wait for. The idtype and id arguments select the child(ren) to wait for, as fol‐ lows: idtype == P_PID Wait for the child whose process ID matches id. idtype == P_PGID Wait for any child whose process group ID matches id. idtype == P_ALL Wait for any child; id is ignored. The child state changes to wait for are specified by ORing one or more of the following flags in options: WEXITED Wait for children that have terminated. WSTOPPED Wait for children that have been stopped by delivery of a signal. WCONTINUED Wait for (previously stopped) children that have been resumed by delivery of SIGCONT. The following flags may additionally be ORed in options: WNOHANG As for waitpid(). WNOWAIT Leave the child in a waitable state; a later wait call can be used to again retrieve the child status information. Upon successful return, waitid() fills in the following fields of the siginfo_t structure pointed to by infop: si_pid The process ID of the child. si_uid The real user ID of the child. (This field is not set on most other implementations.) si_signo Always set to SIGCHLD. si_status Either the exit status of the child, as given to _exit(2) (or exit(3)), or the signal that caused the child to termi‐ nate, stop, or continue. The si_code field can be used to determine how to interpret this field. si_code Set to one of: CLD_EXITED (child called _exit(2)); CLD_KILLED (child killed by signal); CLD_DUMPED (child killed by signal, and dumped core); CLD_STOPPED (child stopped by signal); CLD_TRAPPED (traced child has trapped); or CLD_CONTINUED (child continued by SIGCONT). If WNOHANG was specified in options and there were no children in a waitable state, then waitid() returns 0 immediately and the state of the siginfo_t structure pointed to by infop is unspecified. To distin‐ guish this case from that where a child was in a waitable state, zero out the si_pid field before the call and check for a nonzero value in this field after the call returns. RETURN VALUE wait(): on success, returns the process ID of the terminated child; on error, -1 is returned. waitpid(): on success, returns the process ID of the child whose state has changed; if WNOHANG was specified and one or more child(ren) speci‐ fied by pid exist, but have not yet changed state, then 0 is returned. On error, -1 is returned. waitid(): returns 0 on success or if WNOHANG was specified and no child(ren) specified by id has yet changed state; on error, -1 is returned. Each of these calls sets errno to an appropriate value in the case of an error. ERRORS ECHILD (for wait()) The calling process does not have any unwaited-for children. ECHILD (for waitpid() or waitid()) The process specified by pid (wait‐ pid()) or idtype and id (waitid()) does not exist or is not a child of the calling process. (This can happen for one‘s own child if the action for SIGCHLD is set to SIG_IGN. See also the Linux Notes section about threads.) EINTR WNOHANG was not set and an unblocked signal or a SIGCHLD was caught; see signal(7). EINVAL The options argument was invalid.
wait函数和waitpid函数的区别在于:
下面通过实例来验证wait函数的使用:
1 #include "apue.h" 2 #include <sys/wait.h> 3 4 void pr_exit(int status); 5 6 int main(void) 7 { 8 pid_t pid; 9 int status; 10 11 if((pid = fork()) < 0) 12 err_sys("fork error"); 13 else if(pid == 0) 14 exit(7); 15 16 if(wait(&status) != pid) 17 err_sys("wait error"); 18 pr_exit(status); 19 20 if((pid = fork()) < 0) 21 err_sys("fork error"); 22 else if(pid == 0) 23 abort(); 24 25 if(wait(&status) != pid) 26 err_sys("wait error"); 27 pr_exit(status); 28 29 30 if((pid = fork()) < 0) 31 err_sys("fork error"); 32 else if(pid == 0) 33 status /= 0; 34 35 if(wait(&status) != pid) 36 err_sys("wait error"); 37 pr_exit(status); 38 exit(0); 39 } 40 41 void pr_exit(int status) 42 { 43 if(WIFEXITED(status)) 44 printf("normal termination, exit status = %d\n",WEXITSTATUS(status)); 45 else if(WIFSIGNALED(status)) 46 printf("abnormal termination, signal number = %d%s\n",WTERMSIG(status), 47 #ifdef WCOREDUMP 48 WCOREDUMP(status) ? " (core file generated)" : ""); 49 #else 50 ""); 51 #endif 52 else if(WIFSTOPPED(status)) 53 printf("child stopped, signal number = %d\n",WSTOPSIG(status)); 54 }
上面代码运行的结果是:
normal termination, exit status = 7 abnormal termination, signal number = 6 abnormal termination, signal number = 8
进程篇(3: 基本进程控制:进程的退出)--请参照本博客“操作系统”专栏,布布扣,bubuko.com
进程篇(3: 基本进程控制:进程的退出)--请参照本博客“操作系统”专栏
标签:des c style class blog code
原文地址:http://www.cnblogs.com/jiangheng/p/3763716.html