程序在执行过程经常产生信号,有些是由内核发出,有些是由用户发出。

执行命令kill -l可以查看信号。

QQ截图20160502132059

这些信号由系统定义,他们不是简单的int之类的数据类型,可能是调用一些函数。

这些信号中,10/12是给用户预留使用的,其他信号各有自己相应的含义。代码中无法完美的自定义信号,容易覆盖或产生系统错误,所以还是乖乖用系统提供的信号吧。

信号类似QT的信号槽的关系,一个信号对应一个处理函数,可以对相应的信号进行屏蔽之类的处理。

信号处理函数属于可重入函数,可以随时中断,允许多个副本执行。

信号处理属于异步处理,和主程是分开执行的,内核发送信号只发送一次。一般处理函数仅仅用于通知主程收到信号,有主程处理具体内容。

下面是信号处理代码,分别是内核发送的子进程结束信号和用户自定义信号。

 1 #include <sys/types.h>
 2 #include <unistd.h>
 3 #include <sys/wait.h>
 4 #include <signal.h>
 5 #include <string.h>
 6 #include <iostream>
 7 #include <stdlib.h>
 8 
 9 using namespace std;
10 
11 class sigOp
12 {
13 public:
14     void addSigProcess(int sig,void (*func)(int));
15     void sendSig(const int sig, const int pid);
16 };
17 void sigOp::addSigProcess(int sig,void (*func)(int))
18 {
19     struct sigaction stuSig;
20     memset(&stuSig, '\0', sizeof(stuSig));
21     stuSig.sa_handler = func;
22     stuSig.sa_flags |= SA_RESTART;
23     sigfillset(&stuSig.sa_mask);
24     sigaction(sig, &stuSig, NULL);
25 }
26 void sigOp::sendSig(const int sig, const int pid)
27 {
28     kill(pid, sig);
29     cout<<"send!"<<endl;
30 }
31 void recSig(int sig)
32 {
33     cout<<"rev sig!"<<endl;
34 }
35 void waitchlid(int sig)
36 {
37     pid_t pid;
38     int stat;
39     while((pid = waitpid(-1, &stat, WNOHANG)) > 0);
40 }
41 int main()
42 {
43     sigOp sig;
44     sig.addSigProcess(SIGUSR1, recSig);
45     sig.addSigProcess(SIGCHLD, waitchlid);
46     pid_t pid = fork();
47     if (pid > 0)
48     {
49         sig.sendSig(SIGUSR1, pid);
50     }
51     else
52     {
53         return 0;
54     }
55     while(1);
56     return 0;
57 }

 

当我们不处理SIGCHLD信号时,利用ps -aux查看,可以看到进程属于僵尸态。

image

收到SIGCHLD信号,并且waitpid回收后,没有僵尸进程。

测试结果:

image

image