zoukankan      html  css  js  c++  java
  • Linux C

    Poll就是监控文件是否可读的一种机制,作用与select一样。

    应用程序的调用函数如下:

    int poll(struct pollfd *fds,nfds_t nfds, int timeout);

    Poll机制会判断fds中的文件是否可读,如果可读则会立即返回,返回的值就是可读fd的数量,如果不可读,那么就进程就会休眠timeout这么长的时间,然后再来判断是否有文件可读,如果有,返回fd的数量,如果没有,则返回0. 

    使用非阻塞I/O的应用程序通常会使用select()和poll()系统调用查询是否可对设备进行无阻塞的访问,这两个系统调用最终又会引发设备驱动中的poll()函数被执行

    如果当前不可读(先调用驱动.poll确定是否可读,然后继续do_poll),那么在sys_poll->do_poll中当前进程就会睡眠在等待队列上,这个等待队列是由驱动程序提供的(就是poll_wait中传入的那个)。当可读的时候,驱动程序可能有一部分代码运行了(比如驱动的中断服务

    程序),那么在这部分代码中,就会唤醒等待队列上的进程,也就是之前睡眠的那个,当那个进程被唤醒后do_poll会再一次的调用驱动程序的poll函数,这个时候应用程序就知道是可读的了。

    Demo程序(一个线程中同时监听两个UDP客户程序的数据发送):

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <errno.h>
    
    /// Handle poll input types
    #define POLL_INPUT (POLLIN  | POLLPRI)
    /// Handle poll error types
    #define POLL_ERROR (POLLERR | POLLHUP | POLLNVAL)
    /// Handle pool output types
    #define POLL_OUTPUT (POLLOUT)
    
    
    /// Identify each physical interface
    typedef enum FHandleVal
    {
      INTERFACE_UDP_DCP = 0,
      INTERFACE_UDP_LTE,
     
      INTERFACE_MAX_VAL
    }
    eFHandleVal;
    
    static struct pollfd FDesc[INTERFACE_MAX_VAL];
    
    
    static int rxUDPLTEInit();
    static int rxUDPDCPInit();
    static int rxLteUDPData(int fd);
    static int rxDCPUDPData(int fd);
    
    int rxUDPLTEInit()
    {    
      struct sockaddr_in server_lte_addr;
    
      /// UDP datagram socket
      int sock_Lte_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
      if (sock_Lte_fd < 0)
      {
        // oops
        printf("UDP lte: RX socket failed %d, %s
    ",
                errno, strerror(errno));
        sock_Lte_fd = -errno;
        return -1;
      }
    
      memset(&server_lte_addr,0,sizeof(struct sockaddr_in));
    
      server_lte_addr.sin_family      = AF_INET;
      server_lte_addr.sin_addr.s_addr = htonl(INADDR_ANY);
      server_lte_addr.sin_port        = htons(27358);
    
      int rc = bind(sock_Lte_fd, (struct sockaddr *)&server_lte_addr, sizeof(server_lte_addr));
      if (rc < 0)
      {
        // oops
        printf("UDP: bind(%d, ANY) RX failed: %d, %s
    ",
                sock_Lte_fd, errno, strerror(errno));
        close(sock_Lte_fd);
        sock_Lte_fd = -errno;
      }
      else
      {
        printf("UDP: bind  on RX port %d
    ",27358);
      }
      
      return sock_Lte_fd;    
    }
    
    int rxUDPDCPInit()
    {
      int sock_fd;
      struct sockaddr_in server_addr;
      struct sockaddr_in src_addr;
    
      socklen_t client_len;
    
      memset(&server_addr,0,sizeof(struct sockaddr_in));
      if ((sock_fd = socket(AF_INET, SOCK_DGRAM,0)) < 0)
        {
            perror("socket create error
    ");
            exit(1);
        }
      
      server_addr.sin_family = AF_INET;
      server_addr.sin_port = htons(4004);
      server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
      printf("Ready bind 4004
    ");
       if (bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) < 0)
        {
            perror("bind socket error.
    ");
            exit(1);
        }
        return sock_fd;
    }
    
    int rxDCPUDPData(int fd)
    {
        int rcv_num = -1;
        char rcv_buff[512];
        struct sockaddr_in src_addr;
        socklen_t client_len;
        int encodeNum = -1;
        BSM_t BSMData;
    
        client_len = sizeof(struct sockaddr_in);
        
        rcv_num= recvfrom(fd, rcv_buff, sizeof(rcv_buff), 0, (struct sockaddr*)&src_addr, &client_len);
         if (rcv_num>0)
          {
            rcv_buff[rcv_num] = '';
    
            printf("%s %d says: %s
    ",inet_ntoa(src_addr.sin_addr),ntohs(src_addr.sin_port),rcv_buff);    
    
        }
         else
           {
               perror("recv DCP Data error
    ");
               exit(1);
           }
         return 0;
    }
        
    int rxLteUDPData(int fd)
    {
        int rcv_num = -1;
        char rcv_buff[512];
        struct sockaddr_in src_addr;
        socklen_t client_len;
    
        
        client_len = sizeof(struct sockaddr_in);
            
        rcv_num= recvfrom(fd, rcv_buff, sizeof(rcv_buff), 0, (struct sockaddr*)&src_addr, &client_len);
        if (rcv_num>0)
        {
            rcv_buff[rcv_num] = '';
        
            printf("%s %d says: %s
    ",inet_ntoa(src_addr.sin_addr),ntohs(src_addr.sin_port),rcv_buff);    
    
        }else
           {
               perror("recv LTE-V Data error:");
               exit(1);
           }
    
    }
    int main(void)
    {    
        FDesc[INTERFACE_UDP_LTE].fd = rxUDPLTEInit();
              if (FDesc[INTERFACE_UDP_LTE].fd < 0) exit(1);
    
        FDesc[INTERFACE_UDP_DCP].fd = rxUDPDCPInit();
              if (FDesc[INTERFACE_UDP_DCP].fd < 0) exit(1);
        
         // setup the poll events
         FDesc[INTERFACE_UDP_DCP].events  = POLL_INPUT;
         FDesc[INTERFACE_UDP_LTE].events  = POLL_INPUT;
        
        while (1)
        {
            int Data = poll(FDesc, INTERFACE_MAX_VAL, 1000);
        
              // poll status check
                if (Data < 0)
                {
                      // error
                      printf("Poll error %d '%s'
    ", errno, strerror(errno));
                      
                }
             else if (Data == 0)
                {
                      // timeout
                      printf("Poll timeout
    ");
                      continue;
                }
    
                 // Receive DCP UDP
                if (FDesc[INTERFACE_UDP_DCP].revents & POLL_ERROR)
                {
                   printf("Poll error on UDP (revents 0x%02x)
    ",
                  FDesc[INTERFACE_UDP_DCP].revents);
             }
                if (FDesc[INTERFACE_UDP_DCP].revents & POLL_INPUT)
            {        
                  int Res = rxDCPUDPData(FDesc[INTERFACE_UDP_DCP].fd);
                 if(Res!=0)
                     {
                         
                     }
            }    
                 // Receive LTE UDP
                if (FDesc[INTERFACE_UDP_LTE].revents & POLL_ERROR)
                {
                   printf("Poll error on UDP (revents 0x%02x)
    ",
                  FDesc[INTERFACE_UDP_LTE].revents);
             }
                if (FDesc[INTERFACE_UDP_LTE].revents & POLL_INPUT)
            {
                  int Res = rxLteUDPData(FDesc[INTERFACE_UDP_LTE].fd);
            }
        }
        
        if(FDesc[INTERFACE_UDP_LTE].fd) close(FDesc[INTERFACE_UDP_LTE].fd);
        if(FDesc[INTERFACE_UDP_DCP].fd) close(FDesc[INTERFACE_UDP_DCP].fd);
       return 0;
    }
  • 相关阅读:
    从新浪财经获取金融新闻类数据并进行打分计算
    SQL窗口函数的用法总结
    从新浪财经获取金融新闻类数据并保存到MySQL
    [ZJOI2015]幻想乡战略游戏
    二次剩余入门
    [多校赛20210406]迫害 DJ
    [NOI Online 2021 提高组] 愤怒的小N
    [NOI Online 2021 提高组] 岛屿探险
    「UNR #3」百鸽笼
    [ZJOI2019]开关
  • 原文地址:https://www.cnblogs.com/Pan-Z/p/6628608.html
Copyright © 2011-2022 走看看