概念:

信号时一种异步事件:信号处理函数和程序的主循环式两条不同的执行路线,信号处理函数需要尽可能快地执行完毕,以确保该信号不被屏蔽.(为了避免一些竞态条件,信号在处理期间,系统不会再次出发它)太久.这里就采用一种常用的解决方案是:把信号的主要处理函数逻辑放到程序的主循环中,当信号处理函数被触发时,它只是简单地通知主循环程序接受到信号,并把信号值传递给主函数.主循环在根据接受到的信号值执行目标信号对应的处理逻辑代码.通常采用管道的方式来将"信号"传递给主循环.主程序采用I/O复用模型来将信号事件和其他事件统一处理.即统一事件源.

代码实例:

 #include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h> #define MAX_EVENT_NUMBER 1024
static int pipefd[]; int setnonblocking(int fd){
int old_option=fcntl(fd,F_GETFL);
int new_option=old_option | O_NONBLOCK; fcntl(fd,F_SETFL,new_option);
return old_option;
} void addfd(int epollfd,int fd){
struct epoll_event event;
event.data.fd=fd;
event.events =EPOLLIN | EPOLLET;
epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event);
setnonblocking(fd);
} void sig_handler(int sig){
int save_errno=errno;
int msg=sig;
send(pipefd[],(char*)&msg,,);
errno=save_errno;
} void addsig(int sig){
struct sigaction sa;
memset(&sa,'\0',sizeof(sa));
sa.sa_flags|=SA_RESTART;
sa.sa_handler=sig_handler;
sigfillset(&sa.sa_mask);
assert(sigaction(sig,&sa,NULL)!=-);
} int main(int argc,char* argv[]){
if(argc<=){
printf("usage:%s ip_address port_number\n",argv[]);
return -;
} const char* ip=argv[];
int port=atoi(argv[]); struct sockaddr_in server_addr;
memset(&server_addr,,sizeof(server_addr));
server_addr.sin_family=AF_INET;
inet_pton(AF_INET,ip,&server_addr.sin_addr));
server_addr.sin_port=htons(port)); int listenfd=socket(AF_INET,SOCK_STREAM,);
assert(listenfd!=-); int ret=bind(listenfd,(struct sockaddr*)&server_addr,sizeof(server_addr));
assert(ret!=-); ret=listen(listenfd,);
assert(ret!=-); epoll_event events[MAX_EVENT_NUMBER];
int epollfd=epoll_create();
assert(epollfd!=-);
addfd(epollfd,listenfd); ret=socketpair(AF_UNIX,SOCK_STREAM,,pipefd);
assert(ret!=-); setnonblocking(pipefd[]);
addfd(epollfd,pipefd[]); addsig(SIGHUP);
addsig(SIGCHLD);
addsig(SIGTERM);
addsig(SIGINT);
bool stop_server=false; while(!stop_server){
int number=epoll_wait(epollfd,events,MAX_EVENT_NUMBER,-);
if((number<) && (errno!=EINTR)){
printf("epoll failure\n");
break;
} else{
for(int i=;i<number;i++){
int sockfd=events[i].data.fd;
if(sockfd==listenfd){
struct sockaddr_in client;
bzero(&client,sizeof(client));
socklen_t len=sizeof(client); int connfd=accept(sockfd,(struct sockaddr*)&client,&len);
addfd(epollfd,connfd);
} else if(sockfd==pipefd[] && events[i].events & EPOLLIN){
char signals[];
memset(signals,'\0',sizeof(signals)); int ret=recv(sockfd,signals,,);
if(ret<){
continue;
}
else if(ret==){
continue;
} else{
for(int i=;i<ret;i++){
switch(signals[i])){
case SIGCHLD:
case SIGHUP:
{
continue;
} case SIGTERM:
case SIGINT:
{
stop_server=true;
}
}
}
}
} else{
}
}
}
}
printf("close fds\n");
close(listenfd);
close(pipefd[]);
close(pipefd[]);
return ;
}

Linux-统一事件源的更多相关文章

  1. 统一事件源epoll代码示例

    可以将信号注册进pipe管道的写端,通过对读端的监听,来实现统一事件源. #include <sys/types.h> #include <sys/socket.h> #inc ...

  2. study notes: high performance linux server programming

    1:linux网络API分为:socker地址API,socker基础API,网络信息API 1,socker地址API:包含IP地址和端口(ip, port).表示TCP通信的一端. 2,socke ...

  3. Linux高性能server编程——信号及应用

     信号 信号是由用户.系统或者进程发送给目标进程的信息.以通知目标进程某个状态的改变或系统异常. Linux信号可由例如以下条件产生: 对于前台进程.用户能够通过输入特殊的终端字符来给它发送信号. ...

  4. 第2章 Linux系统安装(2)_Linux系统分区及文件系统

    2. 系统分区 2.1 分区类型 (1)主分区:最多只能有4个 (2)扩展分区 ①最多只能有1个,主分区加扩展分区最多有4个. ②不能写入数据,只能包含逻辑分区 (3)逻辑分区 2.2 格式化(高级格 ...

  5. 13.linux中断处理程序

    linux中断处理程序 一.中断处理流程 在linux内核代码中进入entry-armv.S目录: linux统一的入口:__irq svc. 进入了统一的入口之后,程序跳到irq_handler标号 ...

  6. Linux爆新漏洞,长按回车键70秒即可获得root权限

    漏洞来源这个安全问题来源于Cryptsetup存在的一个漏洞(CVE-2016-4484).Cryptsetup是在Linux统一密钥设置(Linux Unified Key Setup, LUKS) ...

  7. linux概念之/proc与/sys

    http://blog.chinaunix.net/uid-1835494-id-3070465.html  proc/x:1/sched http://bbs.chinaunix.net/threa ...

  8. 【Linux】常用命令

    一.文件结构     /:       根目录 /bin:    系统所需要的那些命令位于此目录. /boot:   Linux的内核及引导系统程序所需要的文件目录,GRUB或LILO系统引导管理器也 ...

  9. 菜鸟必须知道的linux的文件目录结构

    Linux文件目录结 / 根目录,所有的目录.文件.设备都在/之下,/就是Linux文件系统的组织者,也是最上级的领导者. /bin bin就是二进制(binary)英文缩写.在一般的系统当中,你都可 ...

随机推荐

  1. JDK + Tomcat 安装配置

    学习Java 开发的第一步就是配置环境,今天第一次配置,把过程记录下以备后用. 一.下载JDK.Tomcat JDK:http://www.oracle.com/technetwork/java/ja ...

  2. google反向代理网址收集

    前言 亲,还在为谷歌被墙而懊恼么?还在苦苦搜集FQ手段么?往下看吧? 最近在网站链接来源统计中,发现了很多反向代理了谷歌的链接,故搜集在这里,供需要的人使用,使用如下链接谷歌搜素不需要FQ哦?下面地址 ...

  3. zip命令的用法

    语法zip [参数] [打包后的文件名] [打包的目录路径] 参数列表-a 将文件转成ASCII模式-F 尝试修复损坏的压缩文件-h 显示帮助界面-m 将文件压缩之后,删除源文件-n 特定字符串,不压 ...

  4. 面试题:获取大量数据中某一条的index

    提问: 群里分享了一个面试题:页面里有很多条数据,怎么知道这条数据的index,并且不使用循环? 分析: 如果在数组里,直接用indexOf,但对于对象会比较麻烦. 在页面上,不使用循环的话,可以用定 ...

  5. angularjs中{{}} 加载出现闪烁问题

    在head标签中加入 [ng-cloak] { display: none !important; } 在页面的body标签上添加 ng-cloak 可以解决页面上先后加载闪烁问题

  6. 递归转手工栈处理的一般式[C语言]

    是任意形式的递归,是化解的一般式. 主题所谓的“递归调用化解为栈处理”,意思是,将递归函数调用化解为“一个由stack_push stack_pop stack_top等函数调用组成的循环式子”.这里 ...

  7. Java Json开源解析包 google-gson download(下载)

    官方下载地址:http://code.google.com/p/google-gson/ http://files.cnblogs.com/hnrainll/google-gson-2.1-relea ...

  8. leetcode: sortlist之四种方法

    原题链接:https://oj.leetcode.com/problems/sort-list/ 题目:空间复杂度为常数,时间复杂度为O(nlogn)的排序链表实现 方法一:第一想法是模拟数组的快速排 ...

  9. BZOJ2768: [JLOI2010]冠军调查

    2768: [JLOI2010]冠军调查 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 484  Solved: 332[Submit][Status ...

  10. bzoj 1196

    http://www.lydsy.com/JudgeOnline/problem.php?id=1196 二分+并查集 一共有2*M条路径,我们首先将这2*M条路径按费用排序. 然后二分最大费用的公路 ...