首页 > 代码库 > 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-统一事件源