免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3083 | 回复: 2
打印 上一主题 下一主题

恳求指教!!一个线程异步信号的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-06 22:53 |只看该作者 |倒序浏览
我想做一个程序的效果是线程在得到主控制的进程发出的信号的时候才会运行,但是在运行的时候发现线程注册的信号回调函数不能工作,我看书上说的线程本质也是轻量的进程,而且本身也有信号处理机制。但是这个信号回调函数为何没有反应?
程序如下

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdint.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. #include <signal.h>
  7. #include <errno.h>

  8. /**
  9. * 搭建一个线程,开始阻塞,然后
  10. * 遇到一个信号后解除阻塞,开始
  11. * 工作
  12. */
  13. //线程控制结构体
  14. typedef struct pthread_control
  15. {
  16.         uint8_t flag:1;
  17.         uint8_t flag_b:1;
  18.         uint8_t flag_c:1;
  19.         uint8_t flag_d:1;
  20.         uint8_t flag_e:1;
  21.         uint8_t flag_f:1;
  22.         uint8_t flag_g:1;
  23.         uint8_t flag_h:1;
  24.         pthread_mutex_t num_mutex;
  25. } pth_ctrl;

  26. #define        PTHREAD_ON_SIG        SIGRTMIN+3
  27. #define        PTHREAD_OFF_SIG        SIGRTMAX-3

  28. void pth_on(int signo)
  29. {
  30.         puts("pthread now on\n");
  31. }

  32. //线程
  33. void *p_func(void *arg)
  34. {
  35.         uint32_t count = 0;
  36.         pth_ctrl *p_c = (pth_ctrl *)arg;
  37.         //安装一个信号处理函数
  38.         signal(PTHREAD_ON_SIG,pth_on);//开启线程信号处理函数
  39.         //线程的异步信号只接收指定信号集给定的信号
  40.         sigset_t p_func_sig;
  41.         sigemptyset(&p_func_sig);//初始化一个空信号集
  42.         sigaddset(&p_func_sig,PTHREAD_ON_SIG);//填加一个信号集
  43.         int sig_arv;//到达的信号
  44.         uint8_t ctrl_flag;
  45.         while(1)
  46.         {
  47.                 pthread_mutex_lock(&(p_c->num_mutex));
  48.                 ctrl_flag = p_c->flag;
  49.                 pthread_mutex_unlock(&(p_c->num_mutex));
  50.                 if(ctrl_flag)
  51.                 {
  52.                         sigwait(&p_func_sig,&sig_arv);
  53.                         //p_c->flag = ~(p_c->flag);
  54.                         puts("thread on do what you want\n");
  55.                         ctrl_flag = !ctrl_flag;
  56.                 }
  57.                 pthread_mutex_lock(&(p_c->num_mutex));
  58.                 p_c->flag = ctrl_flag;
  59.                 pthread_mutex_unlock(&(p_c->num_mutex));
  60.                 printf("run %d times\n",count++);
  61.                 sleep(1);
  62.         }
  63. }


  64. int main(int argc,char *argv[])
  65. {
  66.         //初始化这个控制结构体
  67.         pth_ctrl p_c;
  68.         memset(&p_c,0,sizeof(pth_ctrl));
  69.         p_c.flag = 1;
  70.         //线程初始化
  71.         pthread_t newthid;
  72.         if(pthread_create(&newthid,NULL,p_func,&p_c) != 0)
  73.         {
  74.                 perror("thread create failed");
  75.                 return -1;
  76.         }
  77.         //注册一个信号,采用定时器的方式
  78.         //在一定的时间向线程发送信号
  79.         //signal(PTHREAD_CTRL_TIMER,
  80.         while(1)
  81.         {
  82.                 //定时器发送信号
  83.                 sleep(5);
  84.                 pthread_kill(newthid,PTHREAD_ON_SIG);
  85.                 sleep(5);
  86.                 //这里应该使用一个互斥体
  87.                 //将控制标志锁住,防止影
  88.                 //响其他线程
  89.                 pthread_mutex_lock(&(p_c.num_mutex));
  90.                 p_c.flag = 1;
  91.                 pthread_mutex_unlock(&(p_c.num_mutex));
  92.         }
  93.         return 0;
  94. }
复制代码
这个程序运行的效果

  1. thread on do what you want

  2. run 0 times
  3. run 1 times
  4. run 2 times
  5. run 3 times
  6. run 4 times
  7. thread on do what you want

  8. run 5 times
  9. run 6 times
  10. run 7 times
  11. run 8 times
  12. run 9 times
  13. ....
复制代码
这个程序运行的时候线程等待进程发送信号,然后解除阻塞运行,然后运行一段时间后,主线程修改和进程共用的一个变量然后线程重新进入阻塞状态。但是就是没有发现主进程发送信号的时候,线程注册的信号函数被调用(本来应该打印一句话)。不知道是不是使用方法没有对??恳求指教!!谢谢!!

论坛徽章:
0
2 [报告]
发表于 2011-12-19 16:40 |只看该作者
linux 多线程信号总结(一)
1. 在多线程环境下,产生的信号是传递给整个进程的,一般而言,所有线程都有机会收到这个信号,进程在收到信号的的线程上下文执行信号处理函数,具体是哪个线程执行的难以获知。
2 signal函数 BSD/Linux的实现并不在信号处理函数调用时,恢复信号的处理为默认,而是在信号处理时阻塞此信号,直到信号处理函数返回。其他实现可能在调用信号处理函数时,恢复信号的处理为默认方式,因而需要在信号处理函数中重建信号处理函数为我们定义的处理函数,在这些系统中,较好的方法是使用sigaction来建立信号处理函数。
3 发送信号给进程,哪个线程会收到? APUE说,在多线程的程序中,如果不做特殊的信号阻塞处理,当发送信号给进程时,由系统选择一个线程来处理这个信号。
4 如果进程中,有的线程可以屏蔽了某个信号,而某些线程可以处理这个信号,则当我们发送这个信号给进程或者进程中不能处理这个信号的线程时,系统会将这个信号投递到进程号最小的那个可以处理这个信号的线程中去处理。
5 如果我们同时注册了信号处理函数,同时又用sigwait来等待这个信号,谁会取到信号?经过实验,Linux上sigwait的优先级高。6 在Linux中的posix线程模型中,线程拥有独立的进程号,可以通过getpid()得到线程的进程号,而线程号保存在pthread_t的值中。而主线程的进程号就是整个进程的进程号,因此向主进程发送信号只会将信号发送到主线程中去。如果主线程设置了信号屏蔽,则信号会投递到一个可以处理的线程中去。
7 当调用SYSTEM函数去执行SHELL命令时,可以放心的阻塞SIGCHLD,因为SYSTEM会自己处理子进程终止的问题。
8 使用sleep()时,要以放心的去阻塞SIGALRM信号,目前sleep函数都不会依赖于ALRM函数的SIGALRM信号来工作。

论坛徽章:
0
3 [报告]
发表于 2011-12-23 08:35 |只看该作者
sigwait的第二个参数是返回的信号值,你在后面进行判断,例如:

sigwait(&p_func_sig,&sig_arv);

if (PTHREAD_ON_SIG == sig_arv)
{
  puts("test: pthread now on\n");
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP