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 }

 

posted @ 2014-09-23 22:29  晓风_7  阅读(653)  评论(0编辑  收藏  举报