Linux信号 之 pthread_sigmask函数使用

本文通过分析LTP测试用例disktest/signals.c中的pthread_sigmask使用,结合man手册示例,深入探讨信号处理机制。实验表明,在主线程休眠期间,子线程能捕获USR1信号;而在主线程和子线程同时阻塞于sigwait时,只有主线程能响应QUIT信号,揭示了主线程优先级特性。

        在阅读ltp/testcases/kernel/io/disktest/signals.c代码时,setup_sig_mask()调用了pthread_sigmask()函数,好久没有写代码了,关于这部分代码竟没看明白,故查阅linux自带的manual手册(#man pthread_sigmask)以下代码就是man手册中给出的例子,为了理解信号的处理机制,稍作修改,废话不多说了,请看运行case。

        编译:gcc pthread_sigmask.c -lpthread

        运行结果

       $ ./a.out &
       [3] 3782$ kill -USR1 3782
       $ kill -USR1 3782
       [sig_thread] Signal handling thread got signal 10
       $ kill -QUIT 3782
       [main] Signal handling thread got signal 3
       $ kill -USR1 3782
       [sig_thread] Signal handling thread got signal 10
       $ kill -QUIT 3782
       [sig_thread] Signal handling thread got signal 3
       $ kill -TERM 3782
       [3]+  Terminated              ./a.out

        结果分析

        主线程创建子线程sig_thread后,调用sleep(10)休眠10秒(在这10秒钟,子线程sig_thread已经阻塞在sigwait()函数获取set集合中的信号),主线程在没有执行到sigwait时,执行kill -USR1 3782,子线程获取该信号;一旦主线程和子线程sig_thread都阻塞在sigwait()函数时,当执行kill -QUIT 3782向PID=3782的进程发送信号时,主线程可以获取到,而子线程获取不到,由此可见主线程的优先级高于子线程的。主线程最后执行pause()函数,只有发送QUIT, USR1以外的信号,主线程才可以唤醒,退出,进而进程退出。

/* File: pthread_sigmask.c */
/* Date: 20140609 */

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>

/* Simple error handling 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;
	int s, sig;

	for (;;) {
		s = sigwait(set, &sig);
		if (s != 0)
			handle_error_en(s, "sigwait");
		printf("[sig_thread] Signal handling thread got signal %d\n", sig);
	}
	printf("exit sig_thread\n");
}

int main(int argc, char *argv[])
{
	pthread_t thread;
	sigset_t set;
	int s, sig;

	/* 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_SETMASK, &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 carries on to create other threads and/or do
	   other work */
	sleep(10);
	s = sigwait(&set, &sig);
	if (s != 0)
		handle_error_en(s, "sigwait");
	printf("[main] Signal handling thread got signal %d\n", sig);

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值