(),软件工程师,IBM中国软件开发技术实验室
(),软件工程师,EMC
(),资深软件工程师,IBM
简介:关于代码的可重入性,设计开发人员通常只考虑到线程安全,异步讯号处理函数的安全却常常被忽视。本文首先介绍怎么编撰安全的异步讯号处理函数;之后举例说明在多线程应用中怎样建立模型让异步讯号在指定的线程中以同步的方法处理。
Linux多线程应用中编撰安全的讯号处理函数
在开发多线程应用时,开发人员通常还会考虑线程安全,会使用pthread_mutex去保护全局变量。倘若应用中使用了讯号,并且讯号的形成不是由于程序运行出错,而是程序逻辑须要,例如SIGUSR1、SIGRTMIN等,讯号在被处理后应用程序还将正常运行。在编撰这类讯号处理函数时,应用层面的开发人员却常常忽视了讯号处理函数执行的上下文背景,没有考虑编撰安全的讯号处理函数的一些规则。本文首先介绍编撰讯号处理函数时须要考虑的一些规则;之后举例说明在多线程应用中怎样建立模型让由于程序逻辑须要而形成的异步讯号在指定的线程中以同步的方法处理。
线程和讯号
Linux多线程应用中,每位线程可以通过调用pthread_sigmask()设置本线程的讯号网段。通常情况下,被阻塞的讯号将不能中断此线程的执行,除非此讯号的形成是由于程序运行出错如SIGSEGV;另外不能被忽视处理的讯号SIGKILL和SIGSTOP也难以被阻塞。
当一个线程调用pthread_create()创建新的线程时,此线程的讯号网段会被新创建的线程承继。
POSIX.1标准定义了一系列线程函数的插口,即POSIXthreads(Pthreads)。LinuxC库提供了两种关于线程的实现:LinuxThreads和NPTL(NativePOSIXThreadsLibrary)。LinuxThreads早已过时,一些函数的实现不遵守POSIX.1规范。NPTL依赖Linux2.6内核,愈发遵守POSIX..1规范,但也不是完全遵照。
基于NPTL的线程库linux怎么读,多线程应用中的每位线程有自己独到的线程ID,并共享同一个进程ID。应用程序可以通过调用kill(getpid(),signo)将讯号发送到进程,假如进程中当前正在执行的线程没有妨碍此讯号,则会被中断,线号处理函数会在此线程的上下文背景中执行。应用程序也可以通过调用pthread_kill(pthread_tthread,intsig)将讯号发送给指定的线程,则线号处理函数会在此指定线程的上下文背景中执行。
基于LinuxThreads的线程库,多线程应用中的每位线程拥有自己独到的进程ID,getpid()在不同的线程中调用会返回不同的值linux socket 多线程,所以未能通过调用kill(getpid(),signo)将讯号发送到整个进程。
下文介绍的在指定的线程中以同步的方法处理异步讯号是基于使用了NPTL的LinuxC库。请参考“Linux线程模型的比较:LinuxThreads和NPTL”和“pthreads(7)-Linuxmanpage”进一步了解Linux的线程模型,以及不同版本的LinuxC库对NPTL的支持。
编撰安全的异步讯号处理函数
讯号的形成可以是:
由于讯号是异步风波,即讯号处理函数执行的上下文背景是不确定的,例如一个线程在调用某个库函数时可能会被讯号中断,库函数提早出错返回,转而去执行讯号处理函数。对于上述第三种讯号的形成linux入门,讯号在形成、处理后,应用程序不会中止,还是会继续正常运行linux socket 多线程,在编撰这种讯号处理函数时尤其须要留神,以免破坏应用程序的正常运行。关于编撰安全的讯号处理函数主要有以下一些规则:
从整个Linux应用的角度出发,由于应用中使用了异步讯号,程序中一些库函数在调用时可能被异步讯号中断,此时必须依照errno的值考虑这种库函数调用被讯号中断后的出错恢复处理,例如socket编程中的读操作:
rlen=recv(sock_fd,buf,len,MSG_WAITALL);
if((rlen==-1)&&(errno==EINTR)){
//thiskindoferrorisrecoverable,wecansettheoffsetchange
//‘rlen’as0andcontinuetorecv
}
在指定的线程中以同步的方法处理异步讯号
如上文所述,除了编撰安全的异步讯号处理函数本身有好多的规则禁锢;应用中其它地方在调用可被讯号中断的库函数时还需考虑被中断后的出错恢复处理。这让程序的编撰显得复杂,辛运的是,POSIX.1规范定义了sigwait()、sigwaitinfo()和pthread_sigmask()等插口,可以实现:
这些在指定的线程中以同步方法处理讯号的模型可以防止由于处理异步讯号而给程序运行带来的不确定性和潜在危险。
sigwait
sigwait()提供了一种等待讯号的到来,以串行的形式从讯号队列中取出讯号进行处理的机制。sigwait()只等待函数参数手指定的讯号集,即若果新形成的讯号不在指定的讯号集内,则sigwait()继续等待。对于一个稳定可靠的程序,我们通常会有一些疑惑:
笔者写了一小段测试程序来测试sigwait在讯号处理时的一些规则。
清单1.sigwait_test.c
本文原创地址://gulass.cn/ldxcyyzbxaqd.html编辑:刘遄,审核员:暂无