统一事件源简介

服务器编程中通常有三大类事件需要处理,一类是I/O事件,一类是信号事件,一类是时间事件。
信号事件是一种异步事件,当信号来临时,主逻辑会被打断去执行信号处理函数。而信号到来的时机是不确定,如果此时信号处理函数会去访问一个已经被锁住的资源,那么这个线程就会被阻塞。所以信号处理函数应该是可重入的。
一般信号处理时会将一些信号屏蔽,为了不屏蔽这些信号太久,同时也不至于主逻辑被冲散,一种解决方案是:信号处理函数只是简单的通知主循环(用于处理I/O事件)并告诉信号值,真正的信号处理逻辑被主循环调用,根据信号值做出相应的处理。信号处理函数和主循环之间通常用管道做通信。信号处理函数从管道的写端写入信号值,主循环从管道的读端读取信号值。因为主循环本身就要利用I/O复用函数监听链接进来的socket,所以将这个管道一并注册进I/O复用函数就能在主循环中及时得到信号到来的通知。

int pipefd[2];
... 
void sig_handler(int sig)  
{  
    int save_errno = errno;  
    int msg = sig;  
    send(pipefd[1], (char*)&msg, 1, 0);//将信号按字节写入管道,以通知主循环
    errno = save_errno;  
} 

void addsig(int sig)  
{  
    struct sigaction sa;  
    memset(&sa, '\0', sizeof(sa));  
    sa.sa_handler = sig_handler;  
    sa.sa_flags |= SA_RESTART; //信号如果打断了慢速系统调用,中断处理完成之后继续恢复系统调用
    sigfillset(&sa.sa_mask);//在信号处理函数中屏蔽所有信号
    assert(sigaction(sig, &sa, NULL) != -1);  
}  

void handle_sig(int sig)
{
    switch(sig)
    {
        case SIGCHLD:
            ...
        case SIGHUP:
            ...
        case SIGTERM:
            ...
        case SIGINT:
            ...
        ...
    }
}
...

int main(int argc, char **argv)
{
    ...
    ret=socketpair(PF_UNIX,SOCK_STREAM,0,pipefd);   
    setnonblocking(pipefd[1]);  
    addfd(epollfd,pipefd[0]);  
    while(true)
    {
        int ret = epoll_wait(epollfd, events, MAX_EVENTS, -1);
        for (int i = 0; i < ret; i++)
        {
            if(events[i].fd == pipefd[0] && events[i].events & EPOLLIN) //接收到信号
            {
                char signals[1024];  
                int num = recv(pipefd[0], signals, sizeof(signals), 0);  
                if (num == -1)  
                    continue;  
                else if (num == 0)  
                    continue;  
                else 
                {  
                    //每个信号值占1字节,所以按字节来逐个接收信号  
                    //可能处理的时候收到了多个信号
                    for (int i = 0; i < num; i++) 
                    {
                        handle_sig(signals[i]);
                    } 
                }
            }
        }
    }
    ...
}

参考资料
《Linux高性能服务器编程》
http://www.2cto.com/os/201109/104474.html
http://blog.csdn.net/jasonliuvip/article/details/23305297

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值