UNIX环境高级编程(阅读笔记)---多线程信号
2016-05-10 14:58
696 查看
多线程信号
1.默认情况下,信号将由主进程接收处理,就算信号处理函数是由子线程注册的
2. 每个线程均有自己的信号屏蔽字,可以使用sigprocmask函数来屏蔽某个线程对该信号的响应处理,仅留下需要处理该信号的线程来处理指定的信号。
3. 对某个信号处理函数,以程序执行时最后一次注册的处理函数为准,即在所有的线程里,同一个信号在任何线程里对该信号的处理一定相同
4. 可以使用pthread_kill对指定的线程发送信号
5. 在主进程中对sigmask进行设置后,主进程创建出来的线程将继承主进程的掩码
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
//创建的第一个线程中注册此信号处理函数
void sighandler(int sig) {
printf("SIG:I am thread:%u/n", pthread_self());
}
//创建的第二个线程注册此信号处理函数
void sighandler2(int sig) {
printf("SIG2:I am thread:%u/n", pthread_self());
}
//主进程中注册此信号处理函数
void sighandler_m(int sig) {
printf("SIG:I am main process:%u./n", pthread_self());
}
void *mThread(void *args) {
int i = *(int*)args;
pthread_detach(pthread_self());
printf("I am thread %d:%u/n", i, pthread_self());
if(i == 1)
signal(SIGUSR1, sighandler);
else if(i == 2)
signal(SIGUSR1,sighandler2);
sleep(5);
printf("Thread %d %uwakeup/n", i, pthread_self());
return NULL;
}
int main(int argc, char **argv) {
pthread_t tid1, tid2;
sigset_t mask;
int i;
printf("PID:%d/n", getpid());
printf("I am main process:%u./n", pthread_self());
//注释下面这行,执行会发现主进程在接收到信号时仍然会进入子线程注册的信号处理函数
signal(SIGUSR1, sighandler_m);
i=1;
pthread_create(&tid1, NULL, mThread, &i);
sleep(1);
i=2;
pthread_create(&tid2, NULL, mThread, &i);
sleep(1);
pthread_kill(tid1, SIGUSR1);
sleep(1);
pthread_kill(tid2, SIGUSR1);
// 1. 注释上面四行代码,然后向此进程发送信号,会发现信号始终是被主进程处理的
// 2. 注释上面四行代码,取消下面信号屏蔽代码段的注释,执行并向此进程发送信号,会发现信号被创建的子线程中的其中一个处理
/*
sigemptyset(&mask);
if ( -1 == sigaddset(&mask,SIGUSR1)){
printf("add SIGINT to maskfailed!/n");
return -1;
}
if ( -1 == sigprocmask(SIG_BLOCK, &mask, NULL) ){
printf("sigprocmaskfailed!/n");
return -1;
}
*/
sleep(5);
printf("Main process wake/n");
sleep(3);
return 0;
}
结果:
1.默认情况下,信号将由主进程接收处理,就算信号处理函数是由子线程注册的
2. 每个线程均有自己的信号屏蔽字,可以使用sigprocmask函数来屏蔽某个线程对该信号的响应处理,仅留下需要处理该信号的线程来处理指定的信号。
3. 对某个信号处理函数,以程序执行时最后一次注册的处理函数为准,即在所有的线程里,同一个信号在任何线程里对该信号的处理一定相同
4. 可以使用pthread_kill对指定的线程发送信号
5. 在主进程中对sigmask进行设置后,主进程创建出来的线程将继承主进程的掩码
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
//创建的第一个线程中注册此信号处理函数
void sighandler(int sig) {
printf("SIG:I am thread:%u/n", pthread_self());
}
//创建的第二个线程注册此信号处理函数
void sighandler2(int sig) {
printf("SIG2:I am thread:%u/n", pthread_self());
}
//主进程中注册此信号处理函数
void sighandler_m(int sig) {
printf("SIG:I am main process:%u./n", pthread_self());
}
void *mThread(void *args) {
int i = *(int*)args;
pthread_detach(pthread_self());
printf("I am thread %d:%u/n", i, pthread_self());
if(i == 1)
signal(SIGUSR1, sighandler);
else if(i == 2)
signal(SIGUSR1,sighandler2);
sleep(5);
printf("Thread %d %uwakeup/n", i, pthread_self());
return NULL;
}
int main(int argc, char **argv) {
pthread_t tid1, tid2;
sigset_t mask;
int i;
printf("PID:%d/n", getpid());
printf("I am main process:%u./n", pthread_self());
//注释下面这行,执行会发现主进程在接收到信号时仍然会进入子线程注册的信号处理函数
signal(SIGUSR1, sighandler_m);
i=1;
pthread_create(&tid1, NULL, mThread, &i);
sleep(1);
i=2;
pthread_create(&tid2, NULL, mThread, &i);
sleep(1);
pthread_kill(tid1, SIGUSR1);
sleep(1);
pthread_kill(tid2, SIGUSR1);
// 1. 注释上面四行代码,然后向此进程发送信号,会发现信号始终是被主进程处理的
// 2. 注释上面四行代码,取消下面信号屏蔽代码段的注释,执行并向此进程发送信号,会发现信号被创建的子线程中的其中一个处理
/*
sigemptyset(&mask);
if ( -1 == sigaddset(&mask,SIGUSR1)){
printf("add SIGINT to maskfailed!/n");
return -1;
}
if ( -1 == sigprocmask(SIG_BLOCK, &mask, NULL) ){
printf("sigprocmaskfailed!/n");
return -1;
}
*/
sleep(5);
printf("Main process wake/n");
sleep(3);
return 0;
}
结果:
相关文章推荐
- ASP.NET导入Excel到数据库(SQL)
- java 汉诺塔问题
- thinkphp常用功能
- java定时任务--Timer、TimerTask
- C语言程序的基本语句能完成功能的体会 杜鑫达
- .aspx页面传值到.htm页面的接受参数值写法
- struts2 中,如何覆盖默认的错误消息
- Java之------单机版书店管理系统(设计思想和设计模式系列四)图书模块
- Python基础篇【第8篇】: Socket编程(二)SocketServer
- Python实现欧拉计划22题
- 【S2HS学习笔记】第一章节:Java EE应用和开发环境
- PHP Warning: file_get_contents failed to open stream解决办法
- interface,abstract class,abstract interface Java中的接口,抽象类和抽象接口的异同
- java内存模型
- C语言课程设计第三节课作业刘子威
- 深入分析 Java 中的中文编码问题
- THINKPHP添加不能为空
- 左值、右值与右值引用 & C++11中
- spring的定时任务配置
- Yii2