1 信号基本原理和函数接口
(1)APUE一书中第10章信号
该章节详细讲解了unix系统信号相关的内容,下面这篇文章很好的总结了本章的知识概要,
原文链接:http://blog.csdn.net/atfield/article/details/1532506
每小节知识实例参见《APUE》第十章p233~285.
(2)信号的“未决”和“阻塞”
原文链接:http://blog.csdn.net/sunyubo458/article/details/4484957
“未决”:信号的状态,从信号产生到信号被处理的一段时间;
“阻塞”:阻塞的是信号的处理,不阻塞信号的产生。
信号的阻塞和回复可通过sigprocmask()接口实现。在信号阻塞到回复的期间,是信号的未决状态。
信号经过产生--注册--注销--处理的四个阶段为信号的生命周期。
实时信号(可靠信号):每产生一个就向task_struct结构中注册一个sigquene结构体,注销的时候根据同一信号的注册个数进行不同处理,释放sigquene结构体,且(只有一个,则直接在未决信号集中删除;有多个,则不删除)。
非实时信号(不可靠信号):每产生一个就向task_struct结构中注册一个sigquene结构体,注销的时候根据同一信号的注册个数进行不同处理,释放sigquene结构体,在未决信号集中删除该信号。
2 SIGALRM信号实例----心跳连接
(1)实例背景
在实现心跳连接时,使用的是setitimer()的定时器函数,定时器守护线程每一段时间发送一个SIGALRM信号,主线程收到此信号进行处理,向对方发送一个心跳报文包,感知和对方网络连接的状况(网络线路故障,对方机器宕机等不正常关闭连接的情况)。
(2)关键结构TimerManager
对多并发的连接的处理采用的是EPOLL框架,线程间用管道Pipe进行的通信。系统构造一个全局的定时器管理类对象TimerManager(g_TimerManager),拥有pipe(接收各线程的Timer),pipe[0]读端绑定为RecvData()-->RecvTimer()的读端。在init()时,屏蔽SIGALRM信号,创建定时器线程,线程函数用pthread_procmask()恢复信号,设置定时时间(每一秒钟查询m_TimerList中的时钟是否过期)
struct itimerval {
struct timerval it_interval;
struct timerval it_value;
};
struct timeval {
long tv_sec;
long tv_usec;
};
注释:it_interval为每经过it_intercal时间久发送一个SIGALRM信号;it_value为经过该段时间就发送SIGALRM信号(只发一次)。
信号SIGALRM处理函数为TimerManager.CheckTimeOut()。
需要定时的时候,初始化对象Timer,调用attachTimer()----->registerThread(),将Timer注册到TimerManager的m_TimerList中,绑定读端和写端到全局Epoll中,将Timer对象包装写入m_MsgPipe[1]中。
线程函数功能:恢复SIGALRM后,死循环从m_MsgPipe[0]读取TImer Obj,将Timer Obj insert()进TimerList中,再做checkTimeOut()检查时钟超时。
TimerManager维护的成员有:
int m_MsgPipe1[2]; //for TimerManager receiving Timers from main thread
EpollEvent m_EpollEvent; //EpollEvent Handler
std::map<pthread_t,int> m_MsgRPipeList; //绑定的Timer的Epoll的读端
std::map<pthread_t,int> m_MsgWPipeList; //绑定的Timer的Epoll的写端
std::multiset<Timer*,LessTimer> m_TimerList; // 管理的多线程多个定时器链表
CheckTimeOut():将到时的定时器SendTimer(Timer* P)到TimerManager的m_MsgWPipeList[p->getTid()],触发主线程Epoll的可读事件,m_MsgRPipeList[p->getTid()],调用RecvData(),取出Timer *P,调用p->DoAction(),实现定时发送心跳报文包的任务。
注释:1 文中的TimerManage和Epollr源代码可Pm我获得。
2 代码中设计多重集合的排序,Timer的优先级包装,与本文探讨的定时器信号关系不大,暂不详解。