我正在尝试让信号处理程序在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
抱怨它不在范围内。
有什么指示吗?
你不能从静态方法访问成员变量(只是没有对象)。您也可以将socket_
设置为静态变量,并通过WorkWithSignals<...>::socket_
引用它。
信号处理程序是一个静态方法,因此它不绑定到类的任何实例。
签名手册页包含以下段落(与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();
}