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 }
  • 相关阅读:
    CCS的一些问题
    SignalTapII新特性Storage Qualification
    信号发生器输出幅值与输出阻抗的关系
    关于print函数的一些细节问题探讨
    hp3020 打印机驱动完全卸载方法
    【转】Ruby Selenium 测试
    [nodejs]CoffeeScript里实现Mixin
    [Ruby]ARGF的使用
    【Groovy】使用Maven集成Groovy代码
    [nodejs]optimist库
  • 原文地址:https://www.cnblogs.com/sixue/p/3989501.html
Copyright © 2011-2022 走看看