Linux C - poll示例

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\n",
            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\n",
            sock_Lte_fd, errno, strerror(errno));
    close(sock_Lte_fd);
    sock_Lte_fd = -errno;
  }
  else
  {
    printf("UDP: bind  on RX port %d\n",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\n");
        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\n");
   if (bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) < 0)
    {
        perror("bind socket error.\n");
        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] = ‘\0‘;

        printf("%s %d says: %s\n",inet_ntoa(src_addr.sin_addr),ntohs(src_addr.sin_port),rcv_buff);    

    }
     else
       {
           perror("recv DCP Data error\n");
           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] = ‘\0‘;

        printf("%s %d says: %s\n",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‘\n", errno, strerror(errno));

            }
         else if (Data == 0)
            {
                  // timeout
                  printf("Poll timeout\n");
                  continue;
            }

             // Receive DCP UDP
            if (FDesc[INTERFACE_UDP_DCP].revents & POLL_ERROR)
            {
               printf("Poll error on UDP (revents 0x%02x)\n",
              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)\n",
              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;
}
时间: 2024-10-07 03:18:21

Linux C - poll示例的相关文章

15个实用的Linux find命令示例

妈咪,我找到了! -- 15个实用的Linux find命令示例 http://www.oschina.net/translate/15-practical-linux-find-command-examples?p=2#comments 爹地,我找到了! -- 15个极好的Linux find命令示例 http://www.oschina.net/translate/15-practical-unix-linux-find-command-examples-part-2 15个实用的Linux

妈咪,我找到了! -- 15个实用的Linux find命令示例

妈咪,我找到了! -- 15个实用的Linux find命令示例 英文原文:Mommy, I found it! — 15 Practical Linux Find Command Examples 标签: Linux 659人收藏此文章, 我要收藏66号公路 推荐于 3年前 (共 8 段, 翻译完成于 09-26) (44评 参与翻译(1人): 青崖白鹿 仅中文 | 中英文对照 | 仅英文 | 打印此文章 除了在一个目录结构下查找文件这种基本的操作,你还可以用find命令实现一些实用的操作,使

爹地,我找到了!,15个极好的Linux find命令示例

爹地,我找到了!, 15个极好的Linux find命令示例 英文原文:Daddy, I found it!, 15 Awesome Linux Find Command Examples 标签: Linux 523人收藏此文章, 我要收藏66号公路 推荐于 3年前 (共 9 段, 翻译完成于 09-27) (20评) 参与翻译(3人): 一刀, 和雨冰风, hylent 仅中文 | 中英文对照 | 仅英文 | 打印此文章 前阵子,我们审查了15件实事 find命令的例子(第一部分).查找命令可

&lt;转&gt;13个实用的Linux find命令示例

注:本文摘自青崖白鹿,翻译的妈咪,我找到了! -- 15个实用的Linux find命令示例, 感谢翻译的好文. 除了在一个目录结构下查找文件这种基本的操作,你还可以用find命令实现一些实用的操作,使你的命令行之旅更加简易. 本文将介绍15种无论是于新手还是老鸟都非常有用的Linux find命令. 首先,在你的home目录下面创建下面的空文件,来测试下面的find命令示例. # vim create_sample_files.sh touch MybashProgram.sh touch m

C连接MySQL数据库开发之Linux环境完整示例演示(增、删、改、查)

一.开发环境 ReadHat6.3 32位.mysql5.6.15.gcc4.4.6 二.编译 gcc -I/usr/include/mysql -L/usr/lib -lmysqlclient main.c -o main.out -I:指定mysql头文件所在目录(默认去/usr/include目录下寻找所用到的头文件) -L:指定mysql动态库文件所在目录(默认从/usr/lib目录查找) -l:链接libmysqlclient.so动态库 -o:生成的可执行文件名 三.完整示例 //

linux按键中断驱动示例

#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/delay.h> #include <asm/irq.h> #include <linux/interrupt.h> #include <asm/uaccess.h> #include

15个实用的Linux find命令示例(一)

除了在一个目录结构下查找文件这种基本的操作,你还可以用find命令实现一些实用的操作,使你的命令行之旅更加简易. 本文将介绍15种无论是于新手还是老鸟都非常有用的Linux find命令. 首先,在你的home目录下面创建下面的空文件,来测试下面的find命令示例. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 # vim create_sample_files.sh touch MybashProgram

15个极好的Linux find命令示例(二)

前阵子,我们审查了15件实事 find命令的例子(第一部分).查找命令可以做很多比只是在寻找基于名称的文件 (第2部分)在这篇文章中,让我们来讨论15高级find命令的例子, 包括-根据它访问,修改或改变的时间查找文件,查找文件相比之下,执行操作找到的文件等, 拉梅什纳塔拉詹:这是我的照片中的可爱的小女儿.她很高兴地发现在加州长滩水族馆海狮. 基于访问/修改/更改时间查找文件 你可以找到基于以下三个文件的时间属性的文件. 访问时间的文件.文件访问时,访问时间得到更新. 的文件的修改时间.文件内容

Linux Sed 使用示例

环境:CentOS 鉴于语句描述苍白无力,用例子直接说明. mytxt文件内容: zilzhang 19881110 jiangxi 18 film zhagnsan 21321    sichuan 100 card lisi     3435     hunan   65  TV 1. 找出文件第二行 $ sed -n '2p' mytxt zhagnsan 21321    sichuan 100 card 2. 找出文件第1行到第三行 $ sed -n '1,3p' mytxt zilz