工作点滴(五)Linux多线程编程中的信号问题
来源:互联网 发布:jar软件网站 编辑:程序博客网 时间:2024/06/02 04:16
0 引言
由于工作保密原因,只简单介绍下背景:
本系统中有一个进程A,A中又分别生成5个线程分别为a,b,c,d和e。
其中,
a是主线程(也可以叫做进程A),采用epoll(select)通过socket负责和其他进程间的通信。
b是计时器线程,通过alarm调用产生信号中断来进行计时。(主要是通过类似如下代码进行)
signal(SIGALRM,timer_handle); if(setitimer(ITIMER_REAL,&gTimerVal,NULL) == -1) printf("setitimer error! ");
c,d和e是其他工作线程。
1 问题产生
如果初始化的时候将b线程(计时器线程)打开。
在a线程的socket的通信中就会产生“Interrupted system call”(中文的意思:系统调用被中断)。
如果关闭b线程,该bug就不会产生。
2 分析问题
通过研究epoll及signal原理,发现是由于多线程调用的信号问题产生。
3 解决问题
通过在a线程中设置中断屏蔽即可解决,同时不影响其他线程接受signal。
代码如下:
... struct sigaction action; bzero(&action,sizeof(action));action.sa_sigaction = siga_handler; sigset_t set; sigemptyset(&set) sigaddset(&set,SIGALRM); //sigprocmask(SIG_BLOCK,&set,NULL);pthread_sigmask(SIG_BLOCK,&set,NULL);action.sa_mask = set; action.sa_flags = SA_SIGINFO; // if(sigaction(SIGINT,&action,NULL)==-1)perror("error"),exit(-1); if(sigaction(SIGALRM,&action,NULL)==-1)perror("error"),exit(-1); ...4 总结
4.1 Linux 多线程应用中,每个线程可以通过调用 pthread_sigmask()
设置本线程的信号掩码。一般情况下,被阻塞的信号将不能中断此线程的执行,除非此信号的产生是因为程序运行出错如 SIGSEGV;另外不能被忽略处理的信号 SIGKILL 和 SIGSTOP 也无法被阻塞。
4.2 当一个线程调用 pthread_create()
创建新的线程时,此线程的信号掩码会被新创建的线程继承。
4.3 信号安装最好采用sigaction方式,sigaction,是为替代signal 来设计的较稳定的信号处理,signal的使用比较简单。signal(signalNO,signalproc);
不能完成的任务是:1.不知道信号产生的原因;
2.处理信号中不能阻塞其他的信号
而signaction,则可以设置比较多的消息。尤其是在信号处理函数过程中接受信号,进行何种处理。
sigaction函数用于改变进程接收到特定信号后的行为。4.4 sigprocmask函数只能用于单线程,在多线程中使用pthread_sigmask函数。
4.5 信号是发给进程的特殊消息,其典型特性是具有异步性。
4.6 信号集代表多个信号的集合,其类型是sigset_t。
4.7 每个进程都有一个信号掩码(或称为信号屏蔽字),其中定义了当前进程要求阻塞的信号集。
4.8 所谓阻塞,指Linux内核不向进程交付在掩码中的所有信号。于是进程可以通过修改信号掩码来暂时阻塞特定信号的交付,被阻塞的信号不会影响进程的行为直到该信号被真正交付。
4.9 忽略信号不同于阻塞信号,忽略信号是指Linux内核已经向应用程序交付了产生的信号,只是应用程序直接丢弃了该信号而已。
5 程序实例
#include <stdio.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <signal.h>#include <pthread.h>struct sigaction act;void catchctrlc(int signo){char msg[]="Ctrl-C entered!\n";char errmsg[]="Failed to restore SIGINT\n";int msglen = sizeof(msg);int emsglen = sizeof(errmsg);act.sa_handler = SIG_DFL;write(STDERR_FILENO,msg,msglen);if(sigaction(SIGINT,&act,NULL) == -1)write(STDERR_FILENO,errmsg,emsglen);}int main(){act.sa_handler = catchctrlc;act.sa_flags = 0;if((sigemptyset(&act.sa_mask) == -1) ||(sigaction(SIGINT,&act,NULL) == -1))perror("Failed to set SIGINT to handle Ctrl-c");for(;;);return 0;}
运行结果:
lab@ubuntu:~/ctest/signal$ ./cc //运行程序 //回车^CCtrl-C entered! //第一次按Ctrl+c //回车^C //第二次按Ctrl+clab@ubuntu:~/ctest/signal$
- 工作点滴(五)Linux多线程编程中的信号问题
- linux 多线程编程的信号问题
- Linux多线程中的信号
- linux多线程编程(五)
- linux系统编程之信号(五):信号集操作函数,信号阻塞与未决
- linux系统编程之信号(五):信号集操作函数,信号阻塞与未决
- unix编程(五)信号
- linux系统编程之信号(五):实时信号与sigqueue函数
- linux系统编程之信号(五):实时信号与sigqueue函数
- Linux 多线程编程 与 信号处理
- 工作中的点滴记录
- 工作中的点滴
- 多线程编程点滴
- Linux 多线程应用中的信号处理
- Linux开发--多线程中的信号处理
- Linux 多线程编程问题
- Linux信号编程实践(三) 信号在内核中的表示(sigaction&sigqueue)
- Linux 多线程编程的问题(转)
- 2011-11-17 彻底明白Java的IO系统---JAVA之精髓IO流!
- oracle表分区详解
- The Kernel Boot Process
- 二维数组指针
- 实现STM32中USART的DMA(转)
- 工作点滴(五)Linux多线程编程中的信号问题
- 浅谈SQLite——查询处理及优化
- Hibernate 乐观锁与悲观锁
- Array基本创建
- ADT离线安装
- nginx 自动安装脚本 For cPanel
- ASP.NET安全问题
- 一个关于linux进程函数kill的问题
- ext的datagrid删除最后数据时候不更新的解决