本节介绍对信号执行的操作。
pthread_sigmask(3C) 对线程执行 sigprocmask(2) 对进程所执行的操作。pthread_sigmask() 可以设置 thread 的信号掩码。创建新的线程时,其初始掩码是从其创建者继承的。
在多线程进程中对 sigprocmask() 执行调用等效于对 pthread_sigmask() 执行调用。有关更多信息,请参见 sigprocmask(2) 手册页。
pthread_kill(3C) 是 kill(2) 的线程模拟。pthread_kill() 可以将信号发送到特定线程。发送到指定线程的信号不同于发送到进程的信号。将信号发送到进程时,信号可由该进程中的任何线程来处理。通过 pthread_kill() 发送的信号只能由指定线程来处理。
可以使用 pthread_kill() 将信号仅发送到当前进程中的线程。由于 thread_t 类型的线程标识符的范围是本地,因此不能指定当前进程范围以外的线程。
通过目标线程接收信号时,调用的操作(处理程序 SIG_DFL 或 SIG_IGN)通常为全局操作。如果将 SIGXXX 发送到线程,且 SIGXXX 的作用是中止进程,则目标线程接收信号时将中止整个进程。
对于多线程程序,sigwait(2) 是可供使用的首选接口,因为 sigwait() 可以很好地处理异步生成的信号。
sigwait() 将导致调用线程等待,直到由其设置参数标识的任何信号被传送到该线程为止。线程等待的同时,系统将取消屏蔽由设置参数标识的信号,但调用返回时将恢复原始掩码。
由设置参数标识的所有信号必定会在所有线程(包括调用线程)上受到阻塞。否则,sigwait() 可能无法正常工作。
使用 sigwait() 将线程与异步信号分离。创建一个侦听异步信号的线程时,可同时创建其他线程来阻塞为此进程设置的任何异步信号。
从 Solaris 2.5 发行版开始,可以使用 sigwait() 的两个版本:Solaris 2.5 版本和 POSIX 标准版本。新的应用程序和新的库应该使用 POSIX 标准接口,因为 Solaris 版本在未来的发行版中可能不可用。
以下示例显示了 sigwait() 的两个版本的语法:
#include <signal.h> /* the Solaris 2.5 version*/ int sigwait(sigset_t *set); /* the POSIX standard version */ int sigwait(const sigset_t *set, int *sig);
传送信号时,POSIX sigwait() 将清除暂挂信号,并将信号数字置于 sig 中。许多线程可以同时调用 sigwait(),但是针对每个接收的信号仅返回一个线程。
借助 sigwait(),可以同时处理异步信号。信号到达后,处理这类信号的线程将立即调用 sigwait() 并返回。通过确保所有线程(包括 sigwait() 的调用程序)都屏蔽异步信号,可确保信号仅由预期处理程序处理,且安全地进行处理。
通过始终屏蔽所有线程中的所有信号并在必要时调用 sigwait(),可以使应用程序中依赖于信号的线程的安全性大大提高。
通常,可以创建一个或多个为等待信号而调用 sigwait() 的线程。由于 sigwait() 甚至会检索屏蔽的信号,因此一定要阻塞所有其他线程中的重要信号,以便不会意外传送这些信号。
信号到达时,线程将从 sigwait() 返回,处理信号,并再次调用 sigwait() 以等待更多信号。信号处理线程并不限于使用异步信号安全函数。信号处理线程可采用通常的方式与其他线程同步。MT 接口安全级别定义了异步信号安全类别。
sigtimedwait(3RT) 类似于 sigwait(2),但在指定的时间内没有收到信号时,sigtimedwait() 将失败并返回错误。