找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 7699|回复: 0

ACE 信号使用小结

[复制链接]
发表于 2012-5-23 21:35:20 | 显示全部楼层 |阅读模式
1、 ACE_Sig_ActionACE_Sig_Action是对POSIX sigaction()调用进行封装的封装类。使用ACE_Sig_Action类,只能为一个信号设置一个回调函数。由于回调函数是在信号中断处理上下文中,绝不要在回调函数中做耗时工作。如果有耗时工作要做,我们可以使用ACE_Reactor的通知机制,让耗时工作转会普通的执行上下文去做。
ACE_Sig_Action用法:

  • 定义如下类型的回调函数:typedef void (*ACE_SignalHandler) (int );返回void,接受一个int类型的参数(信号类型值);
  • 实例化ACE_Sig_Action对象,使用ACE_Sig_Action::handler (ACE_SignalHandler)函数设置回调函数,使用ACE_Sig_Action::register_action(int signum)函数,为信号signum设置回调函数。
示例代码:
  1. void my_handler (int signo) {
  2.     // Do something
  3. }
  4. ACE_Sig_Action sig_action;
  5. sig_action.handler (my_handler);
  6. sig_action.register_action (SIGUSR1);
复制代码
在信号中断回调函数执行过程中,依然能够被其它信号中断,但不能被正在处理的信号所中断。对于在某信号的回调处理执行中,收到多次该信号,操作系统将pend此信号,并在上一处理函数执行完后,回调一次。如果我们不希望信号回调函数被中断,我们可以为ACE_Sig_Action实例指定信号掩码。如在上面的实例代码中,如果我们不希望SIGUSR1信号的中断处理函数被信号SIGUSR2中断,可在register_action()方法调用前加上如下代码:

ACE_Sig_Set sig_set;sig_set.add (SIGUSR2);sig_action.mask (sig_set);
注意,我们的许多阻塞的系统调用能够被信号中断,在使用信号时,要为阻塞函数做信号中断处理。对于为sigaction()系统调用提供SA_RESTART标志支持的系统,我们可以对ACE_Sig_Action对象设置SA_RESTART标志,可让被信号中断的系统调用继续执行。不过设置这个标识是不是能够起作用,要参考操作系统的文档,我在自己的linux虚拟机上设置此标识时,并未自动重新调用被信号中断的系统调用。 2、 ACE_Sig_HandlerACE_Sig_Handler提供了一种面向对象的、基于事件处理器的信号登记和分派方案。使用ACE_Sig_Handler提供的这一方案,我们需要从ACE_Event_Handler的派生信号处理类。

2.1 ACE_Sig_Handler用法:

  • 从ACE_Event_Handler派生信号处理类,实现虚方法handle_signal()。
  • 创建信号处理类实例,创建ACE_Sig_Handler实例。调用ACE_Sig_Handler::register_handler (int signo, ACE_Event_Handler *h)方法为信号设置信号处理器。
2.2 示例代码
  1. #include <ace/Sig_Handler.h>
  2. #include <ace/Event_Handler.h>
  3. #include <ace/Log_Msg.h>
  4. #include <ace/Process.h>
  5. class MySignalHandler: public ACE_Event_Handler
  6. {
  7.     public:
  8.         MySignalHandler (int signo): signum_(signo) {}
  9.         virtual ~MySignalHandler () {}
  10.         virtual int handle_signal (int signum,
  11.                 siginfo_t * = 0,
  12.                 ucontext_t * = 0)
  13.         {
  14.             ACE_TRACE (ACE_TEXT ("MySignalHandler::handle_signal"));
  15.             // Make sure the right handler was called back.
  16.             ACE_ASSERT (signum == this->signum_);
  17.             ACE_DEBUG ((LM_DEBUG,
  18.                         ACE_TEXT ("%S occured\n"),
  19.                         signum));
  20.             return 0;
  21.         }
  22.     private:
  23.         int signum_;
  24. };
  25. int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
  26. {
  27.     MySignalHandler h1 (SIGUSR1), h2 (SIGUSR2);
  28.     ACE_Sig_Handler handler;
  29.     handler.register_handler (SIGUSR1, &h1);
  30.     handler.register_handler (SIGUSR2, &h2);
  31.     //ACE_OS::kill (ACE_OS::getpid (), SIGUSR1);
  32.     //ACE_OS::kill (ACE_OS::getpid (), SIGUSR2);
  33.     ACE_Process kill_signal;
  34.     ACE_Process_Options options;
  35.     options.command_line ("./kill_signal %d %d",
  36.             ACE_OS::getpid (),
  37.             SIGUSR1);
  38.     kill_signal.spawn (options);
  39.     options.command_line ("./kill_signal %d %d",
  40.             ACE_OS::getpid (),
  41.             SIGUSR2);
  42.     kill_signal.spawn (options);
  43.    
  44.     int time = 10;
  45.     while (ACE_OS::sleep (time) == -1)
  46.     {
  47.         ACE_DEBUG ((LM_DEBUG,
  48.                     ACE_TEXT ("Sleep() returns -1\n")));
  49.         if (errno == EINTR)
  50.             continue;
  51.         else
  52.         {
  53.             ACE_ERROR_RETURN ((LM_ERROR,
  54.                         ACE_TEXT ("%p\n"),
  55.                         ACE_TEXT ("sleep")), -1);
  56.         }
  57.     }
  58.     return 0;
  59. }
复制代码
其中kill_signal是一个向指定进程ID发送指定信号的小程序。程序派生子进程向自己发送信号。
handle_signal的第一个参数引发中断的信号值。我们不详细介绍handle_signal回调函数的另外两个参数,可参考操作系统文档。其中siginfo_t提供了正在递送信号的起因和属性等信息。
3、 ACE_Sig_Guard信号中断处理是异步的。如果我们在某段代码的执行过程中不希望被信号中断,可以使用ACE_Sig_Guard进行保护。
示例代码如下:
  1. ACE_Sig_Set sig_set;
  2. sig_set.add (SIGUSR1);
  3. sig_set.add (SIGUSR2);
  4. {
  5.     ACE_Sig_Guard sig_guard (&sig_set); // Start of protection
  6.     // Protected Code.
  7.     // Can't interrupt by signals in sig_set
  8. } //End of protection
复制代码
在保护代码执行的过程中,如果sig_set中的信号被递送,则只有保护代码执行完,才回调信号中断处理函数。


作者:wayz11 发表于2012-5-23 16:35:09 原文链接

您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-11-21 21:12 , Processed in 0.016445 second(s), 6 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表