加入收藏 | 设为首页 | 会员中心 | 我要投稿 武汉站长网 (https://www.027zz.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Unix > 正文

Linux多线程中信号解析

发布时间:2023-01-08 13:30:28 所属栏目:Unix 来源:转载
导读: 转:
在Linux的多线程中使用信号机制,与在进程中使用信号机制有着根本的区别,可以说是完全不同。在进程环境中,对信号的处理是,先注册信号处理函数,当信号异步发生时,调用处理函数来处

转:

在Linux的多线程中使用信号机制,与在进程中使用信号机制有着根本的区别,可以说是完全不同。在进程环境中,对信号的处理是,先注册信号处理函数,当信号异步发生时,调用处理函数来处理信号。它完全是异步的(我们完全不知到信号会在进程的那个执行点到来!)。然而信号处理函数的实现,有着许多的限制;比如有一些函数不能在信号处理函数中调用;再比如一些函数read、recv等调用时会被异步的信号给中断(interrupt),因此我们必须对在这些函数在调用时因为信号而中断的情况进行处理(判断函数返回时 enno 是否等于 EINTR)。

但是在多线程中处理信号的原则却完全不同,它的基本原则是:将对信号的异步处理,转换成同步处理,也就是说用一个线程专门的来“同步等待”信号的到来,而其它的线程可以完全不被该信号中断/打断(interrupt)。这样就在相当程度上简化了在多线程环境中对信号的处理。而且可以保证其它的线程不受信号的影响。这样我们对信号就可以完全预测,因为它不再是异步的,而是同步的(我们完全知道信号会在哪个线程中的哪个执行点到来而被处理!)。而同步的编程模式总是比异步的编程模式简单。其实多线程相比于多进程的其中一个优点就是:多线程可以将进程中异步的东西转换成同步的来处理。

1. sigwait函数:

sigwait -wait for a signal

#include int sigwait(const sigset_t *set, int *sig);

DescriptionThe sigwait() functionsuspendsexecution of the calling thread until the delivery of oneofthe signals specified in the signal setset. The functionacceptsthe signal (removesit fromthe pending list of signals), andreturnsthe signal number insig.The operation of sigwait() is the same as sigwaitinfo(2), except that:

* sigwait() only returns the signal number, rather than a siginfo_t structure describing thesignal.*The return values of the two functions are different.Return ValueOn success, sigwait() returns 0. On error, it returns a positive error number.

从上面的man sigwait的描述中,我们知道:sigwait是同步的等待信号的到来,而不是像进程中那样是异步的等待信号的到来。sigwait函数使用一个信号集作为他的参数,并且在集合中的任一个信号发生时返回该信号值,解除阻塞,然后可以针对该信号进行一些相应的处理。

2. 记住:

在多线程代码中,总是使用sigwait或者sigwaitinfo或者sigtimedwait等函数来处理信号。

而不是signal或者sigaction等函数。因为在一个线程中调用signal或者sigaction等函数会改变所以线程中的

信号处理函数。而不是仅仅改变调用signal/sigaction的那个线程的信号处理函数。

3. pthread_sigmask函数:

每个线程均有自己的信号屏蔽集(信号掩码),可以使用pthread_sigmask函数来屏蔽某个线程对某些信号的

响应处理,仅留下需要处理该信号的线程来处理指定的信号。实现方式是:利用线程信号屏蔽集的继承关系

(在主进程中对sigmask进行设置后,主进程创建出来的线程将继承主进程的掩码)

pthread_sigmask - examine and change mask of blocked signals

#include int pthread_sigmask(inthow, const sigset_t *set, sigset_t *oldset);

Compile and link with -pthread.

DESCRIPTIONThe pthread_sigmask() function is just like sigprocmask(2), with the difference thatits usein multithreaded programsis explicitly specified by POSIX.1-2001.Other differences are noted in this page.For a description of the arguments and operation of this function, see sigprocmask(2).

RETURN VALUEOn success, pthread_sigmask() returns 0; on error, it returns an error number.NOTESA new threadinheritsa copy of its creator's signal mask.(from man sigprocmask: )The behavior of the call is dependent on the value of how, as follows.SIG_BLOCKThe set of blocked signals is theunionof the current set andthesetargument.SIG_UNBLOCKThe signals in set are removed from the current set of blockedsignals. It is permissibleto attempt tounblocka signal whichis not blocked.SIG_SETMASKThe set of blocked signals issetto the argumentset.Ifoldsetis non-NULL, the previous value of the signal mask is storedinoldset.Ifsetis NULL, then the signal mask is unchanged (i.e.,howisignored), but the currentvalue of the signal mask is neverthelessreturned inoldset(if it is not NULL).

4. pthread_kill函数:

在多线程程序中unix线程切换,一个线程可以使用pthread_kill对同一个进程中指定的线程(包括自己)发送信号。注意在多线程中

一般不使用kill函数发送信号,因为kill是对进程发送信号,结果是:正在运行的线程会处理该信号,如果该线程没有

注册信号处理函数,那么会导致整个进程退出。

#include int pthread_kill(pthread_tthread, intsig);Compile and link with -pthread.DESCRIPTIONThe pthread_kill() function sends the signalsigto thread, anotherthread in the sameprocess as the caller. The signal is asynchronouslydirected to thread.Ifsigis 0, then no signal is sent, but error checking is still performed; this can beused to check for the existence of a thread ID.RETURN VALUEOn success, pthread_kill() returns 0; on error, it returns an errornumber, and no signalis sent.ERRORSESRCH No thread with the ID thread could be found.EINVAL An invalid signal was specified.

5. 记住:调用sigwait同步等待的信号必须在调用线程中被屏蔽,并且通常应该在所有的线程中被屏蔽(这样可以保证信号绝不会被送到除了调用sigwait的任何其它线程),这是通过利用信号掩码的继承关系来达到的。

(Thesemantics of sigwait require that all threads (includingthe thread calling sigwait) have the signal masked, for

reliable operation. Otherwise, a signal that arrivesnot blocked in sigwaitmight be delivered to another thread.)

6. 代码示例:(from man pthread_sigmask)

#include

#include

#include

#include

#include

#include

/*Simpleerrorhandling functions*/

#define handle_error_en(en,msg)\

do{errno=en;perror(msg);exit(EXIT_FAILURE);}while(0)

static void*

sig_thread(void*arg)

{

sigset_t*set=(sigset_t*)arg;

ints,sig;

for(;;){

s=sigwait(set,&sig);

if(s!=0)

handle_error_en(s,"sigwait");

printf("Signal handling thread got signal %d\n",sig);

}

}

int

main(intargc,char*argv[])

{

pthread_t thread;

sigset_tset;

ints;

/* Block SIGINT;other threads created by main()will inherit

a copy of the signal mask. */

sigemptyset(&set);

sigaddset(&set,SIGQUIT);

sigaddset(&set,SIGUSR1);

s=pthread_sigmask(SIG_BLOCK,&set,NULL);

if(s!=0)

handle_error_en(s,"pthread_sigmask");

s=pthread_create(&thread,NULL,&sig_thread,(void*)&set);

if(s!=0)

handle_error_en(s,"pthread_create");

/* Main thread carriesontocreate other threadsand/ordo

other work */

pause();/*Dummy pause so we can test program*/

return 0;}

编译运行情况:

digdeep@ubuntu:~/pthread/learnthread$ gcc-Wall-pthread-o pthread_sigmask pthread_sigmask.c

digdeep@ubuntu:~/pthread/learnthread$./pthread_sigmask&

[1]4170

digdeep@ubuntu:~/pthread/learnthread$ kill-QUIT%1

digdeep@ubuntu:~/pthread/learnthread$ Signal handling thread got signal 3

digdeep@ubuntu:~/pthread/learnthread$ kill-USR1%1

digdeep@ubuntu:~/pthread/learnthread$ Signal handling thread got signal 10

digdeep@ubuntu:~/pthread/learnthread$ kill-TERM%1

digdeep@ubuntu:~/pthread/learnthread$

[1]+Terminated./pthread_sigmask

digdeep@ubuntu:~/pthread/learnthread$

这个例子演示了:通过在主线程中阻塞一些信号,其它的线程会继承信号掩码,然后专门用一个线程使用sigwait函数来同步的处理信号,使其它的线程不受到信号的影响。

阅读(438) | 评论(0) | 转发(1) |

0

上一篇:pthread_cond_wait函数和pthread_cond_signal函数解析

(编辑:武汉站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章