linux调用信号处理程序后返回,Linux 信号与信号处理分析

-相关核心概念

1.信号(signal)是向进程发送的软件通知,通知进程有事件发生。

2.引发信号的事件发生时,信号就被创建了(generate)了。

3.进程根据信号采取行动时,信号就被传递(deliver)了。

4.信号的生命期(lifetime)就是信号的创建和传递之间的时间间隔。

5.已经生成但还未被传递的信号被称为挂起(pending)的信号。

如果在传递信号时,进程执行了信号处理程序(signal handler),

那么进程就捕捉(catch)到了这个信号。程序可以使用用户编写的函数

名作为参数调用sigaction函数,SIG_DFL表示采取默认动作,SIG_IGN

表示忽略某个信号,那么在传递时那个信号就会被抛弃,不会对程序

产生影响。

信号生成时所采取的动作取决于那个信号当前使用的信号处理程序

和进程信号掩码(process signal mask)。信号掩码中包含一个当前被

阻塞的信号(blocked signal)的列表。被阻塞的信号不会像被忽略的信

号一样被丢弃。如果一个挂起信号被阻塞了,那么当进程接触了对那个

信号的阻塞时,信号就会被传递出去。程序通过调用sigprocmask改变

它的进程信号掩码来阻塞一个信号,通过调用sigaction将信号处理程序

设置为SIG_IGN来忽略一个信号。

-产生信号

调用kill函数可以向指定进程发送指定的信号,调用raise函数可以

使进程向自己发送指定的信号,调用alarm函数可以使进程向自己在经过

指定的秒数之后发送SIGALRM信号。

-信号集

typedef struct {

unsigned long sig[_NSIG_WORDS];

} sigset_t

信号集用来描述信号的集合,linux所支持的所有信号可以全部或部分

的出现在信号集中,主要与信号阻塞相关函数配合使用。

-信号掩码操作

下面是为信号集操作定义的相关函数:

头文件 #include

sigemptyset(sigset_t *set)

//初始化由set指定的信号集,信号集里面的所有信号被清空;

sigfillset(sigset_t *set)

//调用该函数后,set指向的信号集中将包含linux支持的64种信号;

sigaddset(sigset_t *set, int signum)

//在set指向的信号集中加入signum信号;

sigdelset(sigset_t *set, int signum)

//在set指向的信号集中删除signum信号;

sigismember(const sigset_t *set, int signum)

//判定信号signum是否在set指向的信号集中。

-信号的捕捉、忽略和等待

sigaction函数允许调用程序检查或指定与特定信号相关的动作,即处理

信号的行为,或忽略信号。

等待信号处理机制(非忙等),忙等是指连续使用CPU来检测事件的发生,更

有效的方式是将进程或线程挂起知道所等待的事件发生为止。POSIX中的pause,

sigsuspend和sigwait函数提供了三种等待机制。

pause函数将调用线程挂起,知道传递了一个信号为止,这个信号的动作

或者是执行用户定义的处理程序,或者是终止进程。如果信号的动作是终止进

程,pause就不返回。如果信号被进程捕捉,pause就会在信号处理程序返回后返

回。调用形式为:

int pause(void);//总是返回-1。如果被信号中断,pause就将errno设置为EINTR。

sigsuspend函数用参数sigmask指向的信号掩码来阻塞相应的信号,并将进

程或线程挂起,知道进程或线程捕捉到相应的信号。sigsuspend函数在信号处理

程序返回之后返回,并将sigmask指向的信号掩码设置为调用sigsuspend之前的

信号阻塞状态。调用形式为:

int sigsuspend(const sigset_t *sigmask);//总是返回-1。

sigwait函数的形式为:

int sigwait(const sigset_t *restrict sigmask, int *restrict signo);

函数会将调用的线程挂起,直到sigmask信号集中的信号被挂起,然后从挂起的

信号集合中删除那个信号。当sigwait返回时,会把从挂起的信号集合中删除的

那个信号的信号码存储在signo指向的地址中。如果成功,sigwait返回0,否则返

回-1并设置errno。

注意:sigmask指定的信号集中的信号必须在sigwait调用之前被阻塞,并且不能被

忽略,如果为这些信号指定处理函数,这些处理函数也就不会被调用。

-多线程程序中的信号

pthread_kill 函数将指定的信号发送到指定的线程。它的形式为:

int pthread_kill(pthread_t thread, int sig); //成功返回0,否则返回错误码

线程可以用pthread_sigmask函数来检查或设置它的信号掩码。形式为:

int pthread_sigmask(int how, const sigset_t *restrict set, sigset_t

*restrict oset);

参数how:如果为 SIG_SETMASK,线程信号掩码被set取代。

如果为 SIG_BLOCK,会使线程阻塞set中的信号

如果为 SIG_UNBLOCK,会使线程接触对set中的信号的阻塞。

set:为指定的信号集。

oset:保存pthread_sigmask调用前的信号掩码。

-多线程信号处理策略

为信号处理使用特定的线程。主线程在创建线程之前阻塞所有的信号,这样,

所有的线程都将信号阻塞了。然后,专门用来处理信号的线程对那些需要处理的信

号执行sigwait,这样指定的信号都将被这个信号处理线程处理。

-多线程实例

功能描述:主线程在创建子线程之后,等待子线程运行结束,然后继续运行。不同

之处在于,主线程没有调用pthread_join来等待子线程运行结束,而是等待子线程

发送到信号。子线程则在运行结束前向主线程发送信号,来通知主线程。利用信号

机制,实现了线程的同步。

#include

#include

#include

void *threadfunc(void *pvoid)

{

pthread_t *main_tid = (pthread_t*) pvoid;

printf("Child thread says:Hello!World!/n");

pthread_kill(*main_tid,SIGUSR1);

}

int main()

{

sigset_t sigs;

int sig;

pthread_t tid;

pthread_t main_tid;

//阻塞SIGUSR1信号,当线程传递信号时,信号会被挂起

sigemptyset(&sigs);

sigaddset(&sigs,SIGUSR1);

sigprocmask(SIG_BLOCK,&siigs,NULL);

main_tid = pthread_self();

pthread_create(&tid, NULL, &threadfunc, &main_tid);

//等待其它线程发送信号  sigwait(&sigs, &sig);    printf("Main thread says:Hello!World!/n");   return 0;}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值