首页 > 代码库 > Linux-统一事件源
Linux-统一事件源
概念:
信号时一种异步事件:信号处理函数和程序的主循环式两条不同的执行路线,信号处理函数需要尽可能快地执行完毕,以确保该信号不被屏蔽.(为了避免一些竞态条件,信号在处理期间,系统不会再次出发它)太久.这里就采用一种常用的解决方案是:把信号的主要处理函数逻辑放到程序的主循环中,当信号处理函数被触发时,它只是简单地通知主循环程序接受到信号,并把信号值传递给主函数.主循环在根据接受到的信号值执行目标信号对应的处理逻辑代码.通常采用管道的方式来将"信号"传递给主循环.主程序采用I/O复用模型来将信号事件和其他事件统一处理.即统一事件源.
代码实例:
1 #include <sys/types.h> 2 #include <sys/socket.h> 3 #include <netinet/in.h> 4 #include <arpa/inet.h> 5 #include <stdio.h> 6 #include <string.h> 7 #include <stdlib.h> 8 #include <fcntl.h> 9 #include <sys/epoll.h> 10 #include <pthread.h> 11 #include <errno.h> 12 #include <signal.h> 13 14 #define MAX_EVENT_NUMBER 1024 15 static int pipefd[2]; 16 17 int setnonblocking(int fd){ 18 int old_option=fcntl(fd,F_GETFL); 19 int new_option=old_option | O_NONBLOCK; 20 21 fcntl(fd,F_SETFL,new_option); 22 return old_option; 23 } 24 25 void addfd(int epollfd,int fd){ 26 struct epoll_event event; 27 event.data.fd=fd; 28 event.events =EPOLLIN | EPOLLET; 29 epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event); 30 setnonblocking(fd); 31 } 32 33 void sig_handler(int sig){ 34 int save_errno=errno; 35 int msg=sig; 36 send(pipefd[1],(char*)&msg,1,0); 37 errno=save_errno; 38 } 39 40 41 void addsig(int sig){ 42 struct sigaction sa; 43 memset(&sa,‘\0‘,sizeof(sa)); 44 sa.sa_flags|=SA_RESTART; 45 sa.sa_handler=sig_handler; 46 sigfillset(&sa.sa_mask); 47 assert(sigaction(sig,&sa,NULL)!=-1); 48 } 49 50 51 int main(int argc,char* argv[]){ 52 if(argc<=2){ 53 printf("usage:%s ip_address port_number\n",argv[0]); 54 return -1; 55 } 56 57 const char* ip=argv[1]; 58 int port=atoi(argv[2]); 59 60 struct sockaddr_in server_addr; 61 memset(&server_addr,0,sizeof(server_addr)); 62 server_addr.sin_family=AF_INET; 63 inet_pton(AF_INET,ip,&server_addr.sin_addr)); 64 server_addr.sin_port=htons(port)); 65 66 int listenfd=socket(AF_INET,SOCK_STREAM,0); 67 assert(listenfd!=-1); 68 69 int ret=bind(listenfd,(struct sockaddr*)&server_addr,sizeof(server_addr)); 70 assert(ret!=-1); 71 72 ret=listen(listenfd,5); 73 assert(ret!=-1); 74 75 epoll_event events[MAX_EVENT_NUMBER]; 76 int epollfd=epoll_create(5); 77 assert(epollfd!=-1); 78 addfd(epollfd,listenfd); 79 80 ret=socketpair(AF_UNIX,SOCK_STREAM,0,pipefd); 81 assert(ret!=-1); 82 83 setnonblocking(pipefd[1]); 84 addfd(epollfd,pipefd[0]); 85 86 addsig(SIGHUP); 87 addsig(SIGCHLD); 88 addsig(SIGTERM); 89 addsig(SIGINT); 90 bool stop_server=false; 91 92 while(!stop_server){ 93 int number=epoll_wait(epollfd,events,MAX_EVENT_NUMBER,-1); 94 if((number<0) && (errno!=EINTR)){ 95 printf("epoll failure\n"); 96 break; 97 } 98 99 else{100 for(int i=0;i<number;i++){101 int sockfd=events[i].data.fd;102 if(sockfd==listenfd){103 struct sockaddr_in client;104 bzero(&client,sizeof(client));105 socklen_t len=sizeof(client);106 107 int connfd=accept(sockfd,(struct sockaddr*)&client,&len);108 addfd(epollfd,connfd);109 }110 111 else if(sockfd==pipefd[0] && events[i].events & EPOLLIN){112 char signals[1024];113 memset(signals,‘\0‘,sizeof(signals));114 115 int ret=recv(sockfd,signals,1024,0);116 if(ret<0){117 continue;118 } 119 else if(ret==0){120 continue;121 } 122 123 else{124 for(int i=0;i<ret;i++){125 switch(signals[i])){126 case SIGCHLD:127 case SIGHUP:128 {129 continue;130 }131 132 case SIGTERM:133 case SIGINT:134 {135 stop_server=true;136 }137 }138 }139 }140 }141 142 else{143 }144 }145 }146 }147 printf("close fds\n");148 close(listenfd);149 close(pipefd[1]);150 close(pipefd[0]);151 return 0;152 }
Linux-统一事件源
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。