进程线程中睡眠函数(sleep)被信号中断后失效,处理方式总结
2016-08-16 22:59
1896 查看
进程线程中睡眠函数sleep被信号中断后失效,处理方式
很多时候根据程序运行需要,或者调试什么的,需要在程序中延时。当然一般应用的是sleep 函数 , 但是有些时候,如果不注意sleep的用法,那么在多线程编程中,在信号驱使下sleep就会出现失效的特性,或者说起不到延时的作用,原因何在,先看一段代码:
在这段代码中我们可以看到113行if后如果为0 那么程序就会执行 sleep(30),然而程序在真正执行的时候,除非你不进行任何的操作,就等着程序运行结束,你可以看到正常现象。如果你在程序运行期间发送一个SIGINT信号(且在程序运行开始30之内)那么你就会看到,程序直接结束了tid2的线程,sleep并没卵用。
那么是为何呢?
就是因为sleep()运行是程序捕获到一个信号,那么这个信号就会中断sleep,去执行信号所指内容,等处理好信号之后,程序会直接跳到sleep的下一行执行,那么即使sleep秒数没有数完,也照样结束。这就是造成sleep失效的原因。
那么根据这个特性,我提供一种不太精确的解决方法,就是将sleep放到一个循环中去。每次循环延时1秒,因此要延时的秒数约等于循环的次数。在延时精度要求不高的情况下我认为这个方法是可行的,也希望我的方法能够抛砖引玉,得到更多好的方法;
很多时候根据程序运行需要,或者调试什么的,需要在程序中延时。当然一般应用的是sleep 函数 , 但是有些时候,如果不注意sleep的用法,那么在多线程编程中,在信号驱使下sleep就会出现失效的特性,或者说起不到延时的作用,原因何在,先看一段代码:
#include #include #include #include #include #include void tid1_handler(void *arg); void tid1_SIGINT_fun(int signo); void tid1_SIGQUIT_fun(int signo); void tid2_handler(void *arg); void tid2_SIGUSR2_fun(int signo); pthread_t tid1 , tid2; //创建全局的子线程标识 int main(void){ //信号处理,先屏蔽所有的信号 //定义一个信号的集合 sigset_t sig_sets; //置空信号集合 sigemptyset(&sig_sets); //装填所有的信号 sigfillset(&sig_sets); //开始屏蔽 //sigprocmask(SIG_BLOCK , &sig_sets , NULL); pthread_sigmask(SIG_BLOCK , &sig_sets , NULL); //---所有信号屏蔽完成 //创建两个子线程并设置处理函数 pthread_create(&tid1 , NULL , (void *)tid1_handler , NULL); pthread_create(&tid2 , NULL , (void *)tid2_handler , NULL); //while(1); pthread_join(tid1 , NULL); pthread_join(tid2 , NULL); printf("主线程开始退出啦 ....\n"); return 0; } void tid1_handler(void *arg){ //pthread_detach(tid1); //子线程1处理函数 且对 SIGINT 信号开放 //定义一个信号的集合 sigset_t set1; //置空信号集合 sigemptyset(&set1); //装填信号 sigaddset(&set1 , SIGINT); sigaddset(&set1 , SIGQUIT); //安装信号 signal(SIGINT , tid1_SIGINT_fun); signal(SIGQUIT , tid1_SIGQUIT_fun); //放开屏蔽的信号 //int sig = 0; //sigwait(&set1 , &sig); //printf("sig = %d \n",sig); pthread_sigmask(SIG_UNBLOCK , &set1 , NULL); //重新发送可能被屏蔽的信号 int ret = -1; ret = sigpending(&set1); if(ret < 0){ perror("sigpending"); exit(1); } int i = 0; while(1){ printf("tid1 is running [%3d]\n" , i++); sleep(1); } } void tid1_SIGINT_fun(int signo){ //信号执行 if(SIGINT == signo){ printf(" tid1 --->receive a SIGINT signal\n"); pthread_kill(tid2 , SIGUSR2); } } void tid1_SIGQUIT_fun(int signo){ //信号执行 if(SIGQUIT ==signo){ printf(" tid1 --->receive a SIGQUIT signal\n"); exit(1); } } void tid2_handler(void *arg){ //pthread_detach(tid2); //子线程2处理函数 //定义一个信号集合 sigset_t set2; //置空信号集合 sigemptyset(&set2); //装填信号 sigaddset(&set2 , SIGUSR2); //安装信号 signal(SIGUSR2 , tid2_SIGUSR2_fun); //放开屏蔽的信号 pthread_sigmask(SIG_UNBLOCK , &set2 , NULL); //重新发送可能被屏蔽的信号 sigpending(&set2); #if 1 int i = 30; while(i--){ sleep(1); } #else sleep(30); #endif pthread_exit(NULL); } void tid2_SIGUSR2_fun(int signo){ //信号执行 if(SIGUSR2 == signo){ printf(" tid2 --->receive a SIGUSR2 signal \n"); } }
在这段代码中我们可以看到113行if后如果为0 那么程序就会执行 sleep(30),然而程序在真正执行的时候,除非你不进行任何的操作,就等着程序运行结束,你可以看到正常现象。如果你在程序运行期间发送一个SIGINT信号(且在程序运行开始30之内)那么你就会看到,程序直接结束了tid2的线程,sleep并没卵用。
那么是为何呢?
就是因为sleep()运行是程序捕获到一个信号,那么这个信号就会中断sleep,去执行信号所指内容,等处理好信号之后,程序会直接跳到sleep的下一行执行,那么即使sleep秒数没有数完,也照样结束。这就是造成sleep失效的原因。
那么根据这个特性,我提供一种不太精确的解决方法,就是将sleep放到一个循环中去。每次循环延时1秒,因此要延时的秒数约等于循环的次数。在延时精度要求不高的情况下我认为这个方法是可行的,也希望我的方法能够抛砖引玉,得到更多好的方法;
相关文章推荐
- 嵌入式 解决线程使用sleep或usleep等函数导致整个进程睡眠的问题
- 信号中断处理函数中的信号屏蔽
- 子进程在复制父进程的信号处理方式
- 04.多线程--06.【同步方式在线程两种创建方式中的可行性】【同步代码块和同步函数的关系】【多线程程序设计思路总结】
- 杂学杂记(二)改善中断服务中的线程轮询方式为信号异步通知
- Linux的进程/线程间通信方式总结
- 进程与线程(四) linux进程间通信的方式总结
- Linux的进程/线程通信方式总结
- Linux的进程/线程间通信方式总结
- fork - 子进程在复制父进程的信号处理方式
- Linux的进程/线程间通信方式总结
- Linux的进程/线程通信方式总结
- linux系统编程之信号(七):被信号中断的系统调用和库函数处理方式
- Linux的进程/线程通信方式总结
- linux系统编程之信号(七):被信号中断的系统调用和库函数处理方式
- linux信号处理、killall、SIGALRM、sigaction函数和结构体、向进程发送信号
- MFC 友元线程函数方式总结
- linux-0.11中进程睡眠函数sleep_on()解析
- linux系统编程之信号(七):被信号中断的系统调用和库函数处理方式
- Linux的进程/线程间通信方式总结