长春网站优化实战,盐城网站优化公司,深圳论坛,中天建设有限公司官方网站收发信号思想是 Linux 程序设计特性之一#xff0c;一个信号可以认为是一种软中断#xff0c;通过用来向进程通知异步事件。 本文讲述的 信号处理内容源自 Linux man。本文主要对各 API 进行详细介绍#xff0c;从而更好的理解信号编程。 exit(5) 遵循 C11#xff0c; POSI… 收发信号思想是 Linux 程序设计特性之一一个信号可以认为是一种软中断通过用来向进程通知异步事件。 本文讲述的 信号处理内容源自 Linux man。本文主要对各 API 进行详细介绍从而更好的理解信号编程。 exit(5) 遵循 C11 POSIX.1 - 2008 1.库
标准 c 库libc, -lc
2.接口定义 #include stdlib.h[[noreturn]] void exit(int status);
3.接口描述 exit() 函数会导致普通程序终止并将 status 的低字节返回给父进程。 通过 atexit(3) 和 on_exit(3) 注册的所有函数都会被调到顺序和注册顺序相反。如果这些函数中有函数没有返回比如调用了 _exit(2) 或者使用信号杀死了自己那么剩下的函数都不会调用剩下的退出过程也会跳过比如刷新 stdio(3) 流等。如果一个函数通过上面方式注册了多次那么每次都会被调用。 所有打开的 stdio(3) 流都会被刷新并关闭。通过 tmpfile(3) 创建的文件会被删除。 C 标准规定了两个常量EXIT_SUCCESS 和 EXIT_FAILURE可以用来传递给 exit() 指示成功还是失败。
4.返回值 exit() 函数不会返回。
5. 属性 接口属性值exit()线程安全MT-Unsafe race:exit exit() 不是线程安全的会引起数据竞争问题关于数据可以参考 attributes(7)在前几篇文章中也有介绍。 6.注意 如果通过 atexit(3) 或者 on_exit(3) 注册的函数调用 exit() 或者 longjmp(3)那么产生的行为是未定义的。值得注意的是调用 execve(2) 会移除通过 atexit(2) 和 on_exit(3) 注册的函数。 使用 EXIT_SUCCESS 和 EXIT_FAILURE 比用 0 或者非零值1 或 -1更具有移植性尤其是 VMS 会使用不一样的使用习惯。 BSD 尝试标准化了退出码GNU C 库已经采用了可以参考 sysexits.h。 exit() 调用后退出状态必须传递给父进程。主要有三种情况
如果父进程设置 SA_NOCLDWAIT 或者设置了 SIGCHLD 的处置函数为 SIG_IGN那么状态会被忽略子进程立即死掉如果父进程正在等待子进程那么父进程会得到这个退出状态子进程立即死掉否则子进程变成僵尸进程子进程的大多数资源被回收了但是系统进程表中的进程槽会保留来存储一小部分进程信息。这样主要是等待后面父进程通过 waitpid(2)或者其他函数来获得子进程的退出信息那时僵尸进程槽会被释放。 如果系统实现支持 SIGCHLD 信号这时会发送这个信号给父进程。如果父进程设置了 SA_NOCLDWAIT那么是否发送 SIGCHLD 并未定义。
发送给其他进程信号 如果退出进程是会话 leader 并且其终端正控制着会话那么每个前台进程组中的进程都会收到 SIGHUP 信号该终端会从会话上拿掉允许其他新的控制进程获取该控制权。 如果退出进程导致一个进程组成为孤儿并且新产生的孤儿进程组每个进程都停止了那么会在 SIGCONT 信号后再跟上一个 SIGHUP 信号给进程组中的每个进程。参考 setpgid(2) 来查看关于孤儿进程组的解释。 除了以上情况如果要发送的信号是发给要终止进程的子进程的那么通常情况下是不会向子进程发送信号的。然而进程却可以使用 prctl(2) PR_SET_PDEATHSIG 操作来安全如何处理父进程终止时受到的信号。
8.代码 下面程序演示了 fork(2) 和 waitpid() 的用法。程序创建了一个子进程如果没有提供命令行参数那么子进程会使用 pause(2) 来停止允许用户向其发送信号。否则如果指定了命令行参数那么子进程立即返回使用命令行提供的整数作为返回状态值。父进程循环执行通过 waitpid() 来监视子进程使用 W*() 宏来分析返回的状态值。 下面 shell 会话演示了程序的使用 $ ./a.out Child PID is 32360[1] 32359$ kill -STOP 32360stopped by signal 19$ kill -CONT 32360continued$ kill -TERM 32360killed by signal 15[1] Done ./a.out$ 下面是程序源码 #include stdint.h#include stdio.h#include stdlib.h#include sys/wait.h#include unistd.hintmain(int argc, char *argv[]){int wstatus;pid_t cpid, w;cpid fork();if (cpid -1) {perror(fork);exit(EXIT_FAILURE);}if (cpid 0) { /* Code executed by child */printf(Child PID is %jd\n, (intmax_t) getpid());if (argc 1)pause(); /* Wait for signals */_exit(atoi(argv[1]));} else { /* Code executed by parent */do {w waitpid(cpid, wstatus, WUNTRACED | WCONTINUED);if (w -1) {perror(waitpid);exit(EXIT_FAILURE);}if (WIFEXITED(wstatus)) {printf(exited, status%d\n, WEXITSTATUS(wstatus));} else if (WIFSIGNALED(wstatus)) {printf(killed by signal %d\n, WTERMSIG(wstatus));} else if (WIFSTOPPED(wstatus)) {printf(stopped by signal %d\n, WSTOPSIG(wstatus));} else if (WIFCONTINUED(wstatus)) {printf(continued\n);}} while (!WIFEXITED(wstatus) !WIFSIGNALED(wstatus));exit(EXIT_SUCCESS);}}