Linux-统一事件源
概念:
信号时一种异步事件:信号处理函数和程序的主循环式两条不同的执行路线,信号处理函数需要尽可能快地执行完毕,以确保该信号不被屏蔽.(为了避免一些竞态条件,信号在处理期间,系统不会再次出发它)太久.这里就采用一种常用的解决方案是:把信号的主要处理函数逻辑放到程序的主循环中,当信号处理函数被触发时,它只是简单地通知主循环程序接受到信号,并把信号值传递给主函数.主循环在根据接受到的信号值执行目标信号对应的处理逻辑代码.通常采用管道的方式来将"信号"传递给主循环.主程序采用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-统一事件源的更多相关文章
- 统一事件源epoll代码示例
可以将信号注册进pipe管道的写端,通过对读端的监听,来实现统一事件源. #include <sys/types.h> #include <sys/socket.h> #inc ...
- study notes: high performance linux server programming
1:linux网络API分为:socker地址API,socker基础API,网络信息API 1,socker地址API:包含IP地址和端口(ip, port).表示TCP通信的一端. 2,socke ...
- Linux高性能server编程——信号及应用
信号 信号是由用户.系统或者进程发送给目标进程的信息.以通知目标进程某个状态的改变或系统异常. Linux信号可由例如以下条件产生: 对于前台进程.用户能够通过输入特殊的终端字符来给它发送信号. ...
- 第2章 Linux系统安装(2)_Linux系统分区及文件系统
2. 系统分区 2.1 分区类型 (1)主分区:最多只能有4个 (2)扩展分区 ①最多只能有1个,主分区加扩展分区最多有4个. ②不能写入数据,只能包含逻辑分区 (3)逻辑分区 2.2 格式化(高级格 ...
- 13.linux中断处理程序
linux中断处理程序 一.中断处理流程 在linux内核代码中进入entry-armv.S目录: linux统一的入口:__irq svc. 进入了统一的入口之后,程序跳到irq_handler标号 ...
- Linux爆新漏洞,长按回车键70秒即可获得root权限
漏洞来源这个安全问题来源于Cryptsetup存在的一个漏洞(CVE-2016-4484).Cryptsetup是在Linux统一密钥设置(Linux Unified Key Setup, LUKS) ...
- linux概念之/proc与/sys
http://blog.chinaunix.net/uid-1835494-id-3070465.html proc/x:1/sched http://bbs.chinaunix.net/threa ...
- 【Linux】常用命令
一.文件结构 /: 根目录 /bin: 系统所需要的那些命令位于此目录. /boot: Linux的内核及引导系统程序所需要的文件目录,GRUB或LILO系统引导管理器也 ...
- 菜鸟必须知道的linux的文件目录结构
Linux文件目录结 / 根目录,所有的目录.文件.设备都在/之下,/就是Linux文件系统的组织者,也是最上级的领导者. /bin bin就是二进制(binary)英文缩写.在一般的系统当中,你都可 ...
随机推荐
- Clover周报模块 -- 开发总结
2014年7月8日 00:16:05 一.切图 这次开发,切图花了不少时间,样式是用scss写的,第一次用,不过用着用着就发现它的强大,层级.作用域.重用等都非常的方便,还有考拉神器,用着真是爽!不过 ...
- web前端安全相关
burpsuite Burp Suite 是用于攻击web 应用程序的集成平台.它包含了许多工具,并为这些工具设计了许多接口,以促进加快攻击应用程序的过程.所有的工具都共享一个能处理并显示HTTP 消 ...
- flask开发restful api系列(4)--七牛图片服务
上一章我们讲到如何利用alembic来更新数据库,这章,我们讲如何通过七牛服务来存储图片. 像我们大多数公司一样,公司资金比较少,如果自己开发图片服务器,代价太大:如果我们用自己的网站服务器来保存图片 ...
- 深入理解7816(2)---关于ATR
智能卡(此处主要指接触式CPU卡)本身始终处于被动的状态,所以终端设备在和智能卡进行数据交互的时候,需要首先给智能卡发指令,智能卡才会对应地给出应答.而智能卡告诉终端的第一句话就是ATR,亦即“复位应 ...
- KEIL中的一些细节
1.KEIL中的指针: 基于存储器的指针:数据类型 [指向存储区] *[ 指针存储区]指针变量 char xdata * px //px本身存在于自动分配的空间,一般位于data中,指向的内容位于x ...
- ZOJ2317-Nice Patterns Strike Back:矩阵快速幂,高精度
Nice Patterns Strike Back Time Limit: 20000/10000MS (Java/Others)Memory Limit: 128000/64000KB (Java/ ...
- 算法导论(第三版)Exercises4.2(第四章二节)
4.2-1(计算结果) 18 14 62 66 4.2-2(Strassen算法计算矩阵乘法) void multiplyMatrix(int a[], int b[], int n, int r ...
- c语言指向结构体的指针作为函数参数
注意 这里包括形参和实参 struct dangdangtest { ]; int num; }; void change(int num)//值传递 新建一个变量接受传递的值 { num = ; } ...
- maven编写主代码与测试代码
3.2 编写主代码 项目主代码和测试代码不同,项目的主代码会被打包到最终的构件中(比如jar),而测试代码只在运行测试时用到,不会被打包.默认情况下,Maven假设项目主代码位于src/main/ja ...
- .NET 面试题(2)
61.Application .Cookie和 Session 两种会话有什么不同? 1.Application 储存在服务端,没有时间限制,服务器关闭即销毁(前提是自己没写销毁方法) 2.Sessi ...