1. 程式人生 > >執行緒控制-sigwait函式和相關函式解釋

執行緒控制-sigwait函式和相關函式解釋

首先看這篇文章學習執行緒和訊號:http://www.cnblogs.com/clover-toeic/p/4126594.html

然後我寫了一個小程式

#include <stdio.h>
#include <pthread.h>
#include <signal.h>

/*
	測試與執行緒有關的訊號函式	
 
 */

sigset_t new_mask , old_mask;
void *thread_func( void *arg );

int main(int argc , char *argv[]){
	pthread_t thrd;

	pr_mask( " main begin: ");

	//set signal set
	sigemptyset( &new_mask );
	sigaddset( &new_mask , SIGUSR1 );
	sigaddset( &new_mask , SIGINT);

  	/* 
         Block SIGINT; other threads created by main() will inherit
         a copy of the signal mask. 
       */
	//first mask some signals 
	if( pthread_sigmask( SIG_BLOCK , &new_mask , &old_mask)
			!= 0 )
		oops( "thread mask:");

	//建立執行緒
	if( pthread_create( &thrd , NULL , thread_func , NULL)
			!= 0)
		oops( "thread create: ");

	//等待子執行緒結束
	pthread_join( thrd , NULL );

	pr_mask( " main exit: ");

	return 0;
}

void *thread_func( void *arg ){
	int err ,signop;
	int count ;
	
	count = 0;
	pr_mask( " in thread: " );
	while( count++ < 5 ){
		 err = sigwait( &new_mask ,&signop );
		 if( err != 0 )
			 oops( " sigwait: ");
		 switch( signop ){
			case SIGINT:
				printf( " catch sigint.\n ");
				break;
			case SIGUSR1:
				printf( "catch sigusr1.\n " );
				break;
			default:
				printf( "unkown signal.\n");
				break;
		 }
	}
	//reset mask
	if( pthread_sigmask( SIG_SETMASK , &old_mask , NULL) != 0 )
		oops( " thread mask :" );
	pr_mask( " after set mask :");
}

#include <stdio.h>
#include <errno.h>
#include <signal.h>


void pr_mask( const char *str ){
	sigset_t set;
	int errno_save;			//get the pre errno

	errno_save = errno;

	if( sigprocmask( 0, NULL , &set ) == -1 )
		oops( " sigmask" );
	else{
		printf( "%s" , str );
		if( sigismember( &set , SIGQUIT ) )
			printf( " SIGQUIT" );
		if( sigismember( &set , SIGINT ) )
			printf( " SIGINT" );
		if( sigismember( &set , SIGUSR1 ) )
			printf( " SIGUSR1" );
		if( sigismember( &set , SIGALRM ) )
			printf( " SIGALRM" );
		printf("\n");
	}
	errno = errno_save ;
}
#include <stdio.h>
#include <stdlib.h>

void oops(void *msg){
	perror(msg);
	exit(1);
}
然後執行:我傳送 kill -SIGINT 5736 和 kill -SIGUSR1 5736 都能得到正確結果,但是我傳送 kill -SIGALRM 5736 程式就終止了。後來查資料得到了解釋:

在linux系統上預設情況下,訊號將由主程序接收處理,就算訊號處理函式是由子執行緒註冊的, 在Linux中的posix執行緒模型中,執行緒擁有獨立的程序號,可以通過getpid()得到執行緒的程序號,而執行緒號儲存在pthread_t的值中。而主執行緒的程序號就是整個程序的程序號,因此向主程序傳送訊號只會將訊號傳送到主執行緒中去。如果主執行緒設定了訊號遮蔽,則訊號會投遞到一個可以處理的執行緒中去(這解釋了man中的示例程式行為)。



其他可以參考:

http://bbs.chinaunix.net/thread-4088635-1-1.html

http://blog.csdn.net/yusiguyuan/article/details/14230719

http://blog.csdn.net/yusiguyuan/article/details/14237277