linux信号总结

1. 每个信号都有一个名字,都以SIG开头。 信号被定义为正整数。 不存在编号为0的信号。

     头文件是:signal.h

2. 信号是异步事件。产生信号的事件对进程而言是随机的,进程必须告诉内核,当此信号发生时候,请执行以下操作。

3. 信号处理方式,有三种:

     1)忽略信号。  但是SIGKILL和SIGSTOP不能忽略。

     2)捕捉信号。 通知内核在某个信号发生时调用一个用户函数处理,但是SIGKILL和SIGSTOP不能捕捉。

      例如:捕捉到SIGCHLD信号,表示一个子进程结束,在用户函数中调用wait/waitpid结束子进程。

     3)执行系统默认动作。

4. 当一个进程fork时候,其子进程继承父进程的信号处理方式,信号捕捉函数的地址在子进程中是有意义的。

5. 可以使用signal和sigaction处理信号

    1)signal函数

     void signal(int signo, handler hander);

     其中:

     signo--信号名字

     hander有三种选择:1、SIG_IGN 忽略信号  2、SIG_DFL 执行默认动作 3、 捕捉信号后调用的函数地址(回调函数) 例如:typedef void (*handler)(int)

     例如:

    void handler(int signo)

    {

//处理信号

    }

    int main()

   {

if(signal(SIGUSR1, handler) == SIG_ERR)   //捕捉SIGUSR1信号

{

cout<<"error"<<endl;

return 1;

        }

for(;;)

pause();       //挂起程序,直到捕捉到任意一个信号后返回

   }

./a.out &                     //后台执行程序

kill -USR1 PID         //捕捉SIGUSR1信号,执行handler函数。


     2)sigaction函数

     1、信号集的概念

用sigset_t定义信号集。头文件是signal.h

处理信号集的函数:

sigemptyset:初始化信号集;

sigaddset:将信号加入信号集中;     sigdelset:从信号集中删掉信号

sigismember:判断信号是否是信号集的成员

sigpending(sigset_t *set):获取当前已经送到进程,但是被阻塞的所有信号,在set指向的信号集中返回结果。

      2、屏蔽信号(阻塞,延迟信号送到。信号解除阻塞后继续传递)

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

how有三种选择:

SIG_BLOCK:阻塞set信号集

SIG_UNBLOCK:将set信号集解除阻塞

SIG_SETMASK:更新当前阻塞信号集为set指向的信号集。

例如:验证sigprocmask可以阻塞信号

sigset_t set;

sigemptyset(&set);

sigaddset(&set, SIGUSR1);         //将信号加入信号集

sigaddset(&set, SIGUSR2);

signal(SIGUSR1, handler);          //捕捉信号

signal(SIGUSR2, handler);

sigprocmask(SIG_BLOCK, &set, NULL);       //阻塞set信号集

kill(getpid(), SIGUSR1);              //发送信号SIGUSR1和SIGUSR2

kill(getpid(), SIGUSR2);

sleep(2);                                      //为了证明信号被阻塞了,handler不打印内容。

sigprocmask(SIG_UNBLOCK, &set, NULL);    //解除阻塞,handler立即打印内容。

        3、头文件:signal.h

int sigaction(int signo, const struct sigaction *act, struct sigaction *oldact);

注意:signo可以指定除了SIGKILL和SIGSTOP之外的所有的信号;

act:非空,则为要修改的动作;

oldact:非空,返回该信号的上一个动作;

注意:sigaction既可以设置信号的处理方式,也可检验信号的目前设置的处置方式。

4、sigaction结构体:

struct sigaction{

void (*sa_handler)(int);

void (*sa_sigaction)(//);      //sa_handler和sa_sigaction为信号捕捉函数的地址。不要同时指定两个字段值,默认用第一个。

sigset_t sa_mask;

int sa_flags;

void (*sa_restorer)(void);         //已经不再使用

};

说明:

sa_handler:可以是处理信号的三种方式:忽略、执行系统默认动作、捕捉信号调用函数的地址

sa_mask:指定信号处理函数执行过程中应被阻塞的信号,缺省下,当前信号本身被阻塞。

例如:

act.sa_handler = handler;

sigemptyset(&act.sa_mask);

sigaddset(&act.sa_mask, SIGINT);   //在handler执行期间阻塞SIGINT信号,直至handler返回

例如:

void handler(int signo)

{

//处理SIGUSR1消息

cout<<"SIGUSR1"<<endl;

kill(getpid(), SIGUSR2);         //发送SIGUSR2信号,但是之前设置了阻塞,所以信号会被阻塞

sleep(2);       //为了验证SIGUSR2信号确实被阻塞了。

}


void handler_sig(int signo)

{

//处理SIGUSR2消息

cout<<"SIGUSR2"<<endl;

}


int main()

{

struct sigaction act,oldact;

//设置捕捉SIGUSR1

act.sa_handler = handler;

sigemptyset(&act.sa_mask);

sigaddset(&act.sa_mask, SIGUSR2);   //handler函数执行期间,阻塞信号SIGUSR2,直至handler返回

act.sa_flags = 0;

sigaction(SIGUSR1, NULL, &oldact);

if(oldact.sa_handler != SIG_IGN)         //之前处理方式不是忽略掉信号

sigaction(SIGUSR1, &act, NULL);       //安装信号处理,捕捉SIGUSR1信号


//设置捕捉SIGUSR2

act.sa_handler = handler_sig;

sigemptyset(&act.sa_mask);

act.sa_flags = 0;

sigaction(SIGUSR2, NULL, &oldact);

if(oldact.sa_handler != SIG_IGN)       //非忽略处置方式

sigaction(SIGUSR2, &act, NULL);

kill(getpid(), SIGUSR1);        //发送SIGUSR1信号

return 0;

}

5、头文件signal.h

int kill(pid_t pid, int signo);       //发信号给进程

例如:kill(getpid(), SIGINT);

6、可重入函数:即可被中断的函数,即在函数执行任何时候都可被中断的函数。注:malloc是非可重入函数。

7、头文件signal.h

int sigsuspend(const sitset_t *mask);      //挂起进程,等待信号

接收到某个信号前,临时用mask替换进程的信号掩码,挂起进程,直到信号到来。

注意:sigsuspend是原子操作,执行以下四步:(要么都执行,要么都不执行)

1)用mask替换当前信号掩码,阻塞进程

2)收到信号,执行相应处理函数

3)函数返回后,恢复原先的mask

4)sigsuspend返回

实例:

int main()

{

sigset_t newset,old,wait;       //三个信号集

struct sigaction act;

act.sa_handler = handler;

sigemptyset(&act.sa_mask);

act.sa_flags = 0;

sigaction(SIGINT, &act, NULL);          //捕捉SIGINT信号

sigaction(SIGQUIT, &act, NULL);      //捕捉SIGQUIT信号

sigemptyset(&newset);

sigaddset(&newset, SIGINT);            //SIGINT信号加入newset信号集中

sigemptyset(&wait);

sigaddset(&wait, SIGQUIT);           //SIGQUIT信号加入wait信号集中

sigprocmask(SIG_BLOCK, &newset, &old);      //阻塞SIGINT信号,保存之前的信号集

if(sigsuspend(&wait) != -1)   //说明:程序挂起;用wait信号集替换newset,即阻塞SIGQUIT信号,而放通SIGINT信号。当SIGQUIT信号过来,阻塞掉;当SIGINT信号                                                                     过来,调相应函数处理,函数返回后,用newset信号集替换wait,即阻塞SIGINT信号,而放通SIGQUIT信号了。同时sigsuspend返回。

cout<<"error"<<endl;

sigprocmask(SIG_SETMASK, &old, NULL);       //恢复之前的信号集

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值