从C ++中的posix信号处理程序获取对象属性

时间:2012-06-04 05:59:33

标签: c++ linux signals posix

我正在尝试使用C ++工作的信号处理程序,并且无法弄清楚如何使用某些类属性。

当接收到SIGIO信号时,信号处理程序会触发,我需要检查它是否适用于正确的套接字。

我需要做的就是能够访问私人socket_和公众received()

namespace sigh {

 template<typename SomeType>
 class WorkWithSignals
 {
 public:
   void received( unsigned char* data, size_t len, unsigned int from );

 private:
   static void sigio_handler ( int sig, siginfo_t* siginfo, void* empty );
   int socket_;
 };

 extern "C" {
   void sigio_handler ( int sig, siginfo_t* siginfo, void* empty ) {
      if (siginfo->si_fd == ***socket_*** )
        ***received*** ();
   }
 }

}

除了我尝试在sigio_handler的定义之前定义一个静态结构变量之外,在sigio_handler之后定义的类构造函数中填充它,但是sigio_handler抱怨它不是在范围内。

任何指针?

2 个答案:

答案 0 :(得分:1)

您无法从静态方法访问成员变量(没有对象)。您也可以将socket_设为静态变量,并按WorkWithSignals<...>::socket_引用它。

答案 1 :(得分:1)

信号处理程序是一个静态方法,因此它不会绑定到您的类的任何实例。

sigaction手册页包含段落​​(与siginfo_t参数有关):

   * SIGPOLL/SIGIO fills in si_band and si_fd.  The si_band event is a bit
     mask containing the same values as are filled in the revents field by
     poll(2).  The si_fd field indicates the file descriptor for which the
     I/O event occurred.

假设您想继续使用当前基于信号的设计(poll()可能更容易),我建议您将一个静态的文件描述符映射到WorkWithSignals类的实例。

然后在静态信号处理程序中,查找与给定文件描述符(您的socket_字段)相关的实例,然后调用非静态方法来执行特定对象所需的工作。

到WorkWithSignals的decl添加

static std::map<int, WorkWithSignals*> object_registry_;

和源文件中需要的def。通过在注册信号处理程序之前添加到地图并在销毁对象之前从地图中删除来管理地图中的成员资格。然后:

   void sigio_handler ( int sig, siginfo_t* siginfo, void* empty ) {
      std::map<int, WorkWithSignals*>::iterator it = object_registry_.find(siginfo->si_fd);
      if(it == object_registry_.end())
          // handle error case
          assert(false);

      // Check that si_band is masked with the read flag as in the poll() call (look for revents)
      WorkWithSignals* obj = it->second;
      obj->received();
   }