免费注册 查看新帖 |

Chinaunix

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

[C++] Linux下发送自定义信号 C++代码 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-09-11 18:05 |只看该作者 |倒序浏览
今天做的能够实现进程间发送自己定义的信号了,并且可以带参数。
不过发现没多大用处,因为Linux上留了 SIGRTMIN(32)到SIGRTMAX(64)等三十二个可靠信号,可以给应用程序用,基本上已经够用了。
如果用Linux的信号的话,也可以带参数,就是用 sigqueue函数来发送信号,这个函数只可以给一个进程发送信号。

今天做的思路变了一下,就是调用我自己的类的成员函数发送信号之前,我会利用Linux上的共享内在技术(shmget/shmat/shmdt等函数),把要发送的自定义消息,以及所带的参数写到共享内存,然后接收信号的进程收到某个特定的信号之后,再去读共享内存,再把共享内存里面的参数信息交给用户自己定义的信号处理函数处理。



我在CSDN上看见有人问下面这样一个问题:
----------------------------------------------------------------------------------
标题:LINUX下的自定义信号如何实现(不使用系统的SIGUSR1和SIGUSR2)
内容:
(1)例如:   
  #define   SIG_MY_MSG   SIGUSR1+100   
  当我调用kill(0,SIG_MY_MSG)时,系统能够识别出SIG_MY_MSG信号。   
----------------------------------------------------------------------------------

有人说要改Linux内核,将信号的最大值64修改大一些,我不会改内核,写出下面的代码,来实现进程内的的自定义信号发送(进程间的自定义信号发送还得加代码),大家看还有更好的方法吗?拍砖一下,我对自己写的代码没自信,从来没有人看过我写的程序。

大概的思路是这样的:

1、进程里面有一个自定义的单件信号处理类
2、信号处理类里面有一个向量表,来保存用户安装的自定义信号和相应的信号处理函数
3、发送信号时,调用自己的信号发送函数,自己定义的信号发送函数会保存用户发送的信号的值

  1. #include <iostream>
  2. #include <sys/types.h>
  3. #include <sys/params.h>
  4. #include <signal.h>
  5. #include <stdio.h>
  6. #include <unistd.h>
  7. #include <vector>
  8. using namespace std;

  9. #define MYSIG_MSG        SIGUSR1 + 2                        // 自定义的信号,类似于windows平台的 #define WM_MYMESSAGE        WM_USER + 2
  10. #define MYSIG_MSG        SIGUSR1 + 3
  11. #define MYSIG_MSG        SIGUSR1 + 4
  12. #define MYSIG_MSG        SIGUSR1 + 5

  13. void Handler_MSG(unsigned long sig)                // 自定义的信号处理函数,linux的信号处理函数的参数是int,我这里用unsigned long
  14. {
  15.         write( 2, "Handler_MSG\n", 12 );
  16. }

  17. void Handler_MSG2(unsigned long sig)
  18. {
  19.         write( 2, "Handler_MSG2\n", 13 );
  20. }

  21. void Handler_MSG3(unsigned long sig)
  22. {
  23.         write( 2, "Handler_MSG3\n", 13 );
  24. }

  25. void Handler_MSG4(unsigned long sig)
  26. {
  27.         write( 2, "Handler_MSG4\n", 13 );
  28. }

  29. class CSignalHandler                                        // 单件信号处理类,安装和发送自定义的信号都调用此类的成员函数
  30. {
  31. protected:
  32.         typedef void (*SIG_HANDLER_PF)(unsigned long sig);                // 定义一个指向信号处理函数的指针
  33.         struct tagSigaction                                                                                // 定义一个结构体,结构体的一个成员是自定义的信号,另一个成员是个处理自定义信号的函数的指针
  34.         {
  35.                 unsigned long m_ulSigNumber;
  36.                 void (*m_Handler)(unsigned long sig);
  37.         };
  38.         typedef vector<tagSigaction>        SIGACTION_VECTOR;                // 自定义信号的结构体数组
  39.         typedef SIGACTION_VECTOR::iterator SIGACTION_VECTOR_IT;// 迭代器类型,用来访问vector
  40.         SIGACTION_VECTOR        m_SigactionVector;                                        //把自定义的信号及信号处理函数,用vector保存起来
  41.         unsigned long m_ulCurrentSigNumber;                                                // 当前接收到的信号

  42. protected:                                                                                                        // 构造函数定义成保护的,不让用户自己生成信号处理类对象,
  43.         CSignalHandler()
  44.         {
  45.                 ActionDefaultSigHandler();
  46.         }
  47.         ~CSignalHandler()
  48.         {
  49.         }

  50. public:
  51.         static CSignalHandler* GetSignalHandler()                                // 获取信号处理类的全局访问点
  52.         {
  53.                 static CSignalHandler signalhandler;
  54.                 return &signalhandler;
  55.         }

  56. protected:
  57. // 当用户发送一个自定义的信号的时候,该函数就会被调用,然后根据用户发送的信号,调用用户设置的函数进行处理

  58.         static void CustomSigHandler(int sig)                                               
  59. {
  60.                 SIGACTION_VECTOR& SigactionVector = CSignalHandler::GetSignalHandler()->GetSigActionVector();
  61.                 SIGACTION_VECTOR_IT it;
  62.                 for ( it = SigactionVector.begin(); it != SigactionVector.end(); it++ )
  63.                 {
  64.                         if ( (*it).m_ulSigNumber == CSignalHandler::GetSignalHandler()->GetCurrentSigNumber() )
  65.                         {
  66.                                 (*it).m_Handler( CSignalHandler::GetSignalHandler()->GetCurrentSigNumber() );
  67.                         }
  68.                 }
  69.         }

  70.         void ActionDefaultSigHandler()                                                        // 安装默认的SIGUSR1信号处理函数
  71.         {
  72.                 struct sigaction act;
  73.                 act.sa_handler = CSignalHandler::CustomSigHandler;
  74.                 sigemptyset(&act.sa_mask);
  75.                 act.sa_flags = 0;
  76.                 assert( sigaction(SIGUSR1, &act, NULL) >= 0 );
  77.         }

  78.         unsigned long GetCurrentSigNumber() const                                // 获取当前发送的信号
  79.         {
  80.                 return m_ulCurrentSigNumber;
  81.         }

  82.         void SetCurrentSigNumber(unsigned long ulCurrentSigNumber)        // 当用户发送一个信号时,先设置信号值
  83.         {
  84.                 m_ulCurrentSigNumber = ulCurrentSigNumber;
  85.         }

  86.         SIGACTION_VECTOR& GetSigActionVector()                                // 获取用户安装的信号vector的引用
  87.         {
  88.                 return m_SigactionVector;
  89.         }

  90.         int Raise(unsigned long ulSig)                                                // 发送自定义的信号
  91.         {
  92.                 m_ulCurrentSigNumber = ulSig;                                       
  93.                 return raise(SIGUSR1);
  94.         }

  95.         void Sigaction(unsigned long sig, SIG_HANDLER_PF pf)        // 安装自定义的信号
  96.         {
  97.                 struct tagSigaction sigact;
  98.                 sigact.m_ulSigNumber = sig;
  99.                 sigact.m_Handler = pf;
  100.                 m_SigactionVector.push_back(SIGACTION_VECTOR::value_type(sigact));
  101.         }

  102. };

  103. int main(int argc, char* argv[])
  104. {
  105.         CSignalHandler::GetSignalHandler()->Sigaction( MYSIG_MSG, Handler_MSG);                        // 安装自定义的信号
  106.         CSignalHandler::GetSignalHandler()->Sigaction( MYSIG_MSG2, Handler_MSG2);
  107.         CSignalHandler::GetSignalHandler()->Sigaction( MYSIG_MSG3, Handler_MSG3);
  108.         CSignalHandler::GetSignalHandler()->Sigaction( MYSIG_MSG4, Handler_MSG4);

  109.         CSignalHandler::GetSignalHandler()->Raise(MYSIG_MSG);        // 发送自定义的信号
  110.         CSignalHandler::GetSignalHandler()->Raise(MYSIG_MSG2);
  111.         CSignalHandler::GetSignalHandler()->Raise(MYSIG_MSG3);
  112.         CSignalHandler::GetSignalHandler()->Raise(MYSIG_MSG4);

  113.         while (1)
  114.         {
  115.                 sleep(1);
  116.         }
  117.         return 0;
  118. }
复制代码

[ 本帖最后由 luojiafeng1984 于 2007-9-13 17:46 编辑 ]

1.JPG (54.01 KB, 下载次数: 63)

第一段代码

第一段代码

2.JPG (37.76 KB, 下载次数: 59)

第二段代码

第二段代码

3.JPG (37.81 KB, 下载次数: 65)

第三段代码

第三段代码

4.JPG (55.26 KB, 下载次数: 61)

第四段代码

第四段代码

5.JPG (47.76 KB, 下载次数: 61)

第五段代码

第五段代码

6.JPG (58.85 KB, 下载次数: 65)

第六段代码

第六段代码

7.JPG (30.55 KB, 下载次数: 60)

第七段代码

第七段代码

8.JPG (56.45 KB, 下载次数: 61)

修改后的代码

修改后的代码

9.JPG (37.28 KB, 下载次数: 66)

修改后的代码

修改后的代码

10.JPG (53.52 KB, 下载次数: 62)

修改后的代码

修改后的代码

11.JPG (23.69 KB, 下载次数: 60)

修改后的代码

修改后的代码

12.JPG (17.1 KB, 下载次数: 62)

修改后的代码

修改后的代码

论坛徽章:
0
2 [报告]
发表于 2007-09-11 19:13 |只看该作者
你这类貌似只能给进程自己发呀

论坛徽章:
0
3 [报告]
发表于 2007-09-12 09:46 |只看该作者
原帖由 flw2 于 2007-9-11 19:13 发表
你这类貌似只能给进程自己发呀


是这样的,我上面写清楚了,只能给进程自己发。
要实现给其他进程发,可能还需要靠进程通信来实现。有时间我试着做一下。
这些日子在公司闲着没事干。

为什么我发贴,代码断没颜色呢,奇怪了。

论坛徽章:
0
4 [报告]
发表于 2007-11-19 17:56 |只看该作者
兄弟,你误导了大家。
#define MYSIG_MSG        SIGUSR1 + 2                     
#define WM_MYMESSAGE        WM_USER + 2
#define MYSIG_MSG        SIGUSR1 + 3
#define MYSIG_MSG        SIGUSR1 + 4
#define MYSIG_MSG        SIGUSR1 + 5
你所定义的,刚好都是在信号集范围内的,如果你定义一个
#define MYSIG_MSG        SIGUSR1 + 100
这样,你就不会收到任何的信号。

论坛徽章:
38
2017金鸡报晓
日期:2017-02-08 10:39:4215-16赛季CBA联赛之深圳
日期:2023-02-16 14:39:0220周年集字徽章-年
日期:2022-08-31 14:25:28黑曼巴
日期:2022-08-17 18:57:0919周年集字徽章-年
日期:2022-04-25 13:02:5920周年集字徽章-20	
日期:2022-03-29 11:10:4620周年集字徽章-年
日期:2022-03-14 22:35:1820周年集字徽章-周	
日期:2022-03-09 12:51:3220周年集字徽章-年
日期:2022-02-10 13:13:4420周年集字徽章-周	
日期:2022-02-03 12:09:4420周年集字徽章-20	
日期:2022-01-25 20:14:2720周年集字徽章-周	
日期:2022-01-13 15:12:33
5 [报告]
发表于 2007-11-19 18:07 |只看该作者
看起来没啥用。

论坛徽章:
0
6 [报告]
发表于 2007-11-20 13:42 |只看该作者
原帖由 wu_pang_zi 于 2007-11-19 17:56 发表
兄弟,你误导了大家。
#define MYSIG_MSG        SIGUSR1 + 2                     
#define WM_MYMESSAGE        WM_USER + 2
#define MYSIG_MSG        SIGUSR1 + 3
#define MYSIG_MSG        SIGUSR1 + ...



没有啊,可能是我写的程序太乱了,因为是在虚拟机下搞的,我不知道怎么把文件下载到真实的机子上,
定义 SIGUSER + 100是可以的,我这个
发送自定义的信号时就是先发一个 SIGUSER1信号,把自定义的信号值作为参数用共享内存传过去.

不过就如那位兄弟所说,的确是没啥用,一般情况下,Linux的那些信号已经够用了.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP