您的位置:首页 > 运维架构 > Linux

linux下多线程和信号

2011-04-25 11:59 344 查看
说实话,信号是我讨厌的东西,在我些的代码中,我都想用最简单的办法来处理它,现在遇到多线程中信号的处理,APUE中的说法也看得不是很懂,CSDN中一位朋友有如下的总结,先记在这里。

1. 默认情况下,信号将由主进程接收处理,就算信号处理函数是由子线程注册的
2. 每个线程均有自己的信号屏蔽字,可以使用sigprocmask函数来屏蔽某个线程对该信号的响应处理,仅留下需要处理该信号的线程来处理指定的信号。
3. 对某个信号处理函数,以程序执行时最后一次注册的处理函数为准,即在所有的线程里,同一个信号在任何线程里对该信号的处理一定相同
4. 可以使用pthread_kill对指定的线程发送信号

APUE的说法:每个线程都有自己的信号屏蔽字,但是信号的处理是进程中所有的线程共享的,

这意味着尽管单个线程可以阻止某些信号,但当线程修改了与某个信号相关的处理行为后,所

有的线程都共享这个处理行为的改变。这样如果一个线程选择忽略某个信号,而其他线程可

以恢复信号的默认处理行为,或者为信号设置一个新的处理程序,从而可以撤销上述线程的

信号选择。

进程中的信号是送到单个线程的,如果信号与硬件故障或者计时器超时有关,该型号就被发

送到引起该事件的线程中去,而其他的信号则被发送到任意一个线程。

sigprocmask的行为在多线程的进程中没有定义,线程必须使用pthread_sigmask

总结:一个信号可以被没屏蔽它的任何一个线程处理,但是在一个进程内只有一个多个线程共用的处理函数。

------------------------------------------------------我是华丽的分割线---------------------------------------------------------------------

pthread线程库是posix标准,在应用多线程时候难免会遇到线程卡死在慢速IO上面的情况,这种情况应该对线程采用超时机制,即如果超时杀死线程。

杀死线程有两种方式一种是通过pthread_cancel()一种是通过pthread_kill发送信号捕捉信号的方式。

pthread_cancel的使用一直有很多争议,很多人不推荐使用它,在一些linuxBUGReprot上也总是看见它的影子,根据我的使用经验确实觉得这个函数实现的有些不完善。所以这里我给出一个用pthread_kill()发送信号,捕捉信号后线程自己退出的情况。使用时候注意退出时释放掉线程资源。

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <time.h>
pthread_mutex_t mutex_timeout;
pthread_cond_t  cond_timeout;
void alrm_signal(int);
void* thread_work(void*);
int main()
{
pthread_mutex_init(&mutex_timeout, NULL);
pthread_cond_init(&cond_timeout, NULL);
pthread_t thread;
int rc;
struct sigaction action;
memset(&action, 0, sizeof(action));
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
action.sa_handler = alrm_signal;
rc = sigaction(SIGALRM, &action, NULL);
if(rc)
{
printf("sigaction error/n");
exit(1);
}
struct timespec m_time;
//等待30秒
m_time.tv_sec = time(NULL) + 30;
m_time.tv_nsec = 0;

rc = pthread_create(&thread, NULL, thread_work, NULL);
if(rc)
{
printf("Create thread error /n");
exit(1);
}

pthread_mutex_lock(&mutex_timeout);
int res = pthread_cond_timedwait(&cond_timeout, &mutex_timeout, (const struct timespec *)&m_time);
pthread_mutex_unlock(&mutex_timeout);
if(res == ETIMEDOUT)//timeout
{
printf("thread time out!/n");
pthread_kill(thread, SIGALRM);
printf("sigalrm sent/n");
}
else{
printf("back in time/n");
}
printf("Main compelet!/n");

return 0;
}
void alrm_signal(int signo)
{
if(signo != SIGALRM)
{
printf("unexpect signal %d/n", signo);
exit(1);
}

printf("/nSIGALRM has come. alrm_signal will kill timeout thread");
pthread_exit(0);

return;
}
void* thread_work(void * param)
{

while(1)
{
printf("thread is sleeping .../n");
//如果不希望超时,可以通过修改sleep时间让pthread_cond_signal有机会唤醒主线程
sleep(100);
printf("thread wake up/n");

pthread_mutex_lock(&mutex_timeout);
pthread_cond_signal(&cond_timeout);
pthread_mutex_unlock(&mutex_timeout);
}
return NULL;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: