免费注册 查看新帖 |

Chinaunix

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

恳求指教!!!信号用于事件通知中遇到的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-08-31 16:12 |只看该作者 |倒序浏览
我希望有一个进程使用pause挂起,然后这个进程注册了一个信号A,如果我向这个进程发送信号,那么pause的阻塞就解除然后运行代码,运行完后又pause挂起。
例如这段代码在运行的时候,进程就可以不断的响应信号并执行pause后面的代码:
  1. #include <stdio.h>
  2. #include <signal.h>
  3. #include <unistd.h>

  4. #define        UNHAPPEND 0
  5. #define        HAPPEND        1

  6. int flag_happen;

  7. void handler_sigint(int signal)
  8. {
  9.         flag_happen = HAPPEND;
  10. }

  11. int main()
  12. {
  13.         if(signal(SIGINT,handler_sigint) == SIG_ERR)
  14.         {
  15.                 perror("signal");
  16.                 //exit(1);
  17.                 return -1;
  18.         }
  19.         while(1)
  20.         {
  21.                 pause();
  22.                 printf("after event happend\n");
  23.         }

  24.         return 0;
  25. }
复制代码
现在有个想法,在进程中开启一个线程,然后pause阻塞,在线程中发送信号给这个进程后,解除pause阻塞并运行后面的代码。可惜没有达到预期目的。
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <setjmp.h>
  6. #include <signal.h>
  7. #include <pthread.h>

  8. /**
  9. * 线程函数
  10. */
  11. int * sinal_send_pthread(void *arg)
  12. {
  13.         //每隔一段时间发送一个信号
  14.         while(1)
  15.         {
  16.                 sleep(1);
  17.                 raise(SIGRTMIN+15);
  18.                 printf("send signal\n");
  19.         }
  20. }

  21. /**
  22. * 信号函数
  23. */
  24. void signal_handler(int signal,siginfo_t *siginfo,void *pvoid)
  25. {
  26.         printf("recv signal\n");
  27. }

  28. int main()
  29. {
  30.         //注册一个信号
  31.         signal(SIGRTMIN+15,signal_handler);

  32.         //创建一个线程
  33.         pthread_t sig_send;
  34.        
  35.         if(0 != pthread_create(&sig_send,NULL,(void *)sinal_send_pthread,
  36.                                                         NULL))
  37.         {
  38.                 perror("pthread create");
  39.                 exit(1);
  40.         }
  41.         while(1)
  42.         {
  43.                 pause();//这里等待阻塞信号
  44.                 printf("pause end\n");
  45.         }
  46.         return 0;
  47. }
复制代码
这个代码的运行结果是:
recv signal
send signal
recv signal
send signal
……
请教 一下,这种功能该如何实现?感谢!!!

论坛徽章:
0
2 [报告]
发表于 2011-08-31 16:32 |只看该作者
又想到尝试使用
sigsetjmp/siglongjmp函数来实现跳转的方式执行代码
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <setjmp.h>
  6. #include <signal.h>
  7. #include <pthread.h>

  8. /**
  9. * 线程函数
  10. */
  11. int * sinal_send_pthread(void *arg)
  12. {
  13.         //每隔一段时间发送一个信号
  14.         union sigval value;
  15.         while(1)
  16.         {
  17.                 sleep(1);
  18.                 value.sival_ptr = arg;//这里发送信号的时候带上数据jmp_buf env
  19.                 printf("send signal\n");

  20.                 if(sigqueue(getpid(),SIGRTMIN+15,value) < 0)
  21.                 {
  22.                         perror("sigqueue");
  23.                         exit(1);
  24.                 }
  25.         }
  26. }

  27. /**
  28. * 信号函数
  29. */
  30. void signal_handler(int signal,siginfo_t *siginfo,void *pvoid)
  31. {
  32.         printf("recv signal\n");
  33.         siglongjmp(*((jmp_buf *)(siginfo->si_ptr)),1);//跳转到sigsetjmp这个地方
  34. }

  35. int main()
  36. {
  37.         //创建一个跳转变量
  38.         jmp_buf env;

  39.         struct sigaction act;

  40.         //创建一个线程
  41.         pthread_t sig_send;

  42.         if(0 != pthread_create(&sig_send,NULL,(void *)sinal_send_pthread,
  43.                                                         &env))
  44.         {
  45.                 perror("pthread create");
  46.                 exit(1);
  47.         }

  48.         switch(sigsetjmp(env,1))
  49.         {
  50.         case 0:
  51.                 break;
  52.         case 1:
  53.                 printf("pause end xxx\n");
  54.                 break;
  55.         default:
  56.                 break;
  57.         }
  58.         //调整信号使用3参数信号处理函数
  59.         act.sa_sigaction = signal_handler;
  60.         act.sa_flags = SA_SIGINFO;
  61.         sigaction(SIGRTMIN+15,&act,NULL);

  62.         while(1)
  63.         {
  64.                 pause();//这里等待阻塞信号
  65.                 printf("pause end\n");
  66.         }
  67.         return 0;
  68. }
复制代码
结果是这样的
send signal
recv signal
pause end xxx
然后就没有一直这样了。并没有运行pause函数后面的打印语句。
恳求指教,不知道这个该如何实现了!!!

论坛徽章:
0
3 [报告]
发表于 2011-08-31 19:34 |只看该作者
恳求指教!!这个我不是很清楚linux如何阻塞进程然后等待各类信号的响应,如果是进程向进程发送信息,应该是可以正常的响应信号,但是同一个进程下的线程发送信号给本进程似乎就不行了,关键点在于 进程似乎在pause函数里面然后跳不出来了。

论坛徽章:
0
4 [报告]
发表于 2011-09-01 14:45 |只看该作者
如果是两个进程发信号的话,接收信号的进程不仅可以接收到注册的信号并运行绑定的信号处理函数,还能解除pause阻塞,如果一个进程创建一个线程,并使用这个线程给创建自己的进程发送信号的话,进程能接收到信号并运行信号处理函数,但是pause依然阻塞。

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
5 [报告]
发表于 2011-09-02 12:39 |只看该作者
int * sinal_send_pthread(void *arg)
{
        //每隔一段时间发送一个信号
        while(1)
        {
                sleep(1);
                raise(SIGRTMIN+15);
                printf("send signal\n");
        }
}
nervfzb 发表于 2011-08-31 16:12


你这里的 raise() 能把信号送给主进程么?

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
6 [报告]
发表于 2011-09-02 19:53 |只看该作者
现在有个想法,在进程中开启一个线程,然后pause阻塞,在线程中发送信号给这个进程后,解除pause阻塞并运行后面的代码。可惜没有达到预期目的。
nervfzb 发表于 2011-08-31 16:12



    沒有達到預期目的是因為你把 signal 發給了錯誤的 thread:


  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <setjmp.h>
  6. #include <signal.h>
  7. #include <pthread.h>

  8. int * sinal_send_pthread(void *arg)
  9. {
  10.         while(1)
  11.         {
  12.                 sleep(1);
  13.                 //raise(SIGRTMIN+15);
  14.                 pthread_kill(*(pthread_t *)arg, SIGRTMIN+15);
  15.                 printf("send signal\n");
  16.         }
  17. }

  18. void signal_handler(int signal,siginfo_t *siginfo,void *pvoid)
  19. {
  20.         printf("recv signal\n");
  21. }

  22. int main()
  23. {
  24.         signal(SIGRTMIN+15,signal_handler);

  25.         pthread_t main_thread, sig_send;

  26.         main_thread = pthread_self();

  27.         if(0 != pthread_create(&sig_send,NULL,(void *)sinal_send_pthread,
  28.                                 &main_thread))
  29.         {
  30.                 perror("pthread create");
  31.                 exit(1);
  32.         }
  33.         while(1)
  34.         {
  35.                 pause();
  36.                 printf("pause end\n");
  37.         }
  38.         return 0;
  39. }
复制代码
運行的結果:


  1. lee@debian:/tmp$ ./a.out
  2. send signal
  3. recv signal
  4. pause end
  5. send signal
  6. recv signal
  7. pause end
  8. send signal
  9. recv signal
  10. pause end
  11. send signal
  12. recv signal
  13. pause end
  14. send signal
  15. recv signal
  16. pause end
  17. ^C
  18. lee@debian:/tmp$
复制代码

论坛徽章:
0
7 [报告]
发表于 2011-09-08 14:16 |只看该作者
回复 6# MMMIX


    实在太感谢了!!!!
    其实使用raise函数主要是看到这么一句:“raise函数用来给调用它的进程发送信号”。所以我就猜想在一个进程中开启线程,然后调用raise函数,这样就会向进程发送信号:实验结果就是能触发信号函数但无法解除pause阻塞(ubuntu 11.04)。
    您的代码我再好好看看,感谢!!!

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
8 [报告]
发表于 2011-09-08 14:44 |只看该作者
其实使用raise函数主要是看到这么一句:“raise函数用来给调用它的进程发送信号”。所以我就猜想在一个进程中开启线程,然后调用raise函数,这样就会向进程发送信号:
nervfzb 发表于 2011-09-08 14:16



    你应该看看 raise() 的手册 raise(3),而不是猜测它会有什么行为。它的行为在其手册中已经说的非常清楚了,根本不需要猜测。

论坛徽章:
0
9 [报告]
发表于 2011-09-15 21:45 |只看该作者
回复  MMMIX


    实在太感谢了!!!!
    其实使用raise函数主要是看到这么一句:“raise函数用来 ...
nervfzb 发表于 2011-09-08 14:16



    貌似是因为linux中,每个线程都是作为独立进程来执行的。因此创建的新线程实际是另一个进程,调用raise,原有进程收不到信号。所以原有进程一直在pause状态
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP