zoukankan      html  css  js  c++  java
  • 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,'',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
    ",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
    ");
     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,'',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
    ");
    148      close(listenfd);
    149      close(pipefd[1]);
    150      close(pipefd[0]);
    151      return 0;
    152 }
  • 相关阅读:
    angularjs的$on、$emit、$broadcast
    angularjs中的路由介绍详解 ui-route(转)
    ionic入门教程-ionic路由详解(state、route、resolve)(转)
    Cocos Creator 加载使用protobuf第三方库,因为加载顺序报错
    Cocos Creator 计时器错误 cc.Scheduler: Illegal target which doesn't have uuid or instanceId.
    Cocos Creator 构造函数传参警告 Can not instantiate CCClass 'Test' with arguments.
    Cocos Creator 对象池NodePool
    Cocos Creator 坐标系 (convertToWorldSpaceAR、convertToNodeSpaceAR)
    Cocos Creator 常驻节点addPersistRootNode
    Cocos Creator 配合Tiled地图的使用
  • 原文地址:https://www.cnblogs.com/sixue/p/3989501.html
Copyright © 2011-2022 走看看