linux poll函数

  poll函数与select函数差不多

  函数原型:

#include <poll.h>
int poll(struct pollfd fd[], nfds_t nfds, int timeout);

  struct pollfd的结构如下:

struct pollfd{

 int fd; // 文件描述符

 short event;// 请求的事件

 short revent;// 返回的事件

}

  每个pollfd结构体指定了一个被监视的文件描述符。第一个参数是一个数组,即poll函数可以监视多个文件描述符。每个结构体的events是监视该文件描述符的事件掩码,由用户来设置。revents是文件描述符的操作结果事件,内核在调用返回时设置。events中请求的任何事件都可能在revents中返回。合法的事件如下:

  后三个只能作为描述字的返回结果存储在revents中,而不能作为测试条件用于events中。

  这些事件在events域中无意义,因为它们在合适的时候总是会从revents中返回。使用poll()和select()不一样,你不需要显式地请求异常情况报告。
POLLIN | POLLPRI等价于select()的读事件,POLLOUT |POLLWRBAND等价于select()的写事件。POLLIN等价于POLLRDNORM |POLLRDBAND,而POLLOUT则等价于POLLWRNORM。
例如,要同时监视一个文件描述符是否可读和可写,我们可以设置 events为POLLIN |POLLOUT。在poll返回时,我们可以检查revents中的标志,对应于文件描述符请求的events结构体。如果POLLIN事件被设置,则文件描述符可以被读取而不阻塞。如果POLLOUT被设置,则文件描述符可以写入而不导致阻塞。这些标志并不是互斥的:它们可能被同时设置,表示这个文件描述符的读取和写入操作都会正常返回而不阻塞。

  第二个参数nfds:要监视的描述符的数目。

  timeout参数指定等待的毫秒数,无论I/O是否准备好,poll都会返回。timeout指定为负数值表示无限超时;timeout为0指示poll调用立即返回并列出准备好I/O的文件描述符,但并不等待其它的事件。这种情况下,poll()就像它的名字那样,一旦选举出来,立即返回。

  成功时,poll()返回结构体中revents域不为0的文件描述符个数;如果在超时前没有任何事件发生,poll()返回0;失败时,poll()返回-1,并设置errno为下列值之一:
  EBADF:一个或多个结构体中指定的文件描述符无效。
  EFAULT:fds指针指向的地址超出进程的地址空间。
  EINTR:请求的事件之前产生一个信号,调用可以重新发起。
  EINVAL:nfds参数超出PLIMIT_NOFILE值。
  ENOMEM:可用内存不足,无法完成请求。

  

demo:

  代码与上一篇文章中"利用select实现IO多路复用TCP服务端"中代码差不多

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <poll.h>
#define MAX_BUFFER_SIZE 1024
#define IN_FILES 3
#define TIME_DELAY 60*5
#define MAX(a,b) ((a>b)?(a):(b))

int main(int argc ,char **argv)
{
    struct pollfd fds[IN_FILES];
    char buf[MAX_BUFFER_SIZE];
    int i,res,real_read, maxfd;
    fds[0].fd = 0;
    if((fds[1].fd=open("data1",O_RDONLY|O_NONBLOCK)) < 0)
    {
        fprintf(stderr,"open data1 error:%s",strerror(errno));
        return 1;
    }
    if((fds[2].fd=open("data2",O_RDONLY|O_NONBLOCK)) < 0)
        {
                fprintf(stderr,"open data2 error:%s",strerror(errno));
                return 1;
        }
    for (i = 0; i < IN_FILES; i++)
    {
        fds[i].events = POLLIN;
    }
    for(i=0;i<IN_FILES;i++)
    {
        fds[i].events = POLLIN;
    }
    while(fds[0].events || fds[1].events || fds[2].events)
    {
        if (poll(fds, IN_FILES, TIME_DELAY) <= 0)
           {
            printf("Poll error\n");
            return 1;
        }
        for (i = 0; i< IN_FILES; i++)
        {
            if (fds[i].revents)
            {
                memset(buf, 0, MAX_BUFFER_SIZE);
                real_read = read(fds[i].fd, buf, MAX_BUFFER_SIZE);
                if (real_read < 0)
                {
                    if (errno != EAGAIN)
                    {
                        return 1;
                    }
                }
                else if (!real_read)
                {
                    close(fds[i].fd);
                    fds[i].events = 0;
                }
                else
                {
                    if (i == 0)
                    {
                        if ((buf[0] == ‘q‘) || (buf[0] == ‘Q‘))
                        {
                            return 1;
                        }
                    }
                    else
                          {
                               buf[real_read] = ‘\0‘;
                               printf("%s", buf);
                          }
                }
            }
        }
    }
    exit(0);
}
时间: 2024-11-03 13:53:53

linux poll函数的相关文章

linux C poll 函数使用

在学习linux 并发非阻塞服务器时候.看到有使用poll 函数的方式.初步理解并编写程序进行了测试. 服务器: #include <unistd.h> #include <sys/types.h> /* basic system data types */ #include <sys/socket.h> /* basic socket definitions */ #include <netinet/in.h> /* sockaddr_in{} and o

Linux网络编程——I/O复用之poll函数

一.回顾前面的select select优点: 目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点 select缺点: 1.每次调用 select(),都需要把 fd 集合从用户态拷贝到内核态,这个开销在 fd 很多时会很大,同时每次调用 select() 都需要在内核遍历传递进来的所有 fd,这个开销在 fd 很多时也很大. 2.单个进程能够监视的文件描述符的数量存在最大限制,在 Linux 上一般为 1024,可以通过修改宏定义甚至重新编译内核的方式提升这一限制,但是这样也会造成效

linux poll

man poll: NAME poll, ppoll - wait for some event on a file descriptor SYNOPSIS #include <poll.h> int poll(struct pollfd *fds, nfds_t nfds, int timeout); #define _GNU_SOURCE /* See feature_test_macros(7) */ #include <poll.h> int ppoll(struct po

linux poll机制使用(一)

一.poll机制的作用 1.poll机制的作用 在前面的使用中断的的方式来读取按键值(linux 中断管理(四)).使用这种方式读取按键,如果按键没有按下的时候,应用程序会一直处于睡眠的状态.如果想要即使按键没有按下,在一定的时间后也能返回,要实现这种功能,可以使用poll机制.(select IO复用和epoll也可以实现这种功能,这里只写poll机制) 二.poll机制的应用编程 1.应用层函数接口 1).API: int poll(struct pollfd *fds, nfds_t nf

linux poll机制分析(二)

一.回顾 在linux poll机制使用(一)写了个实现poll机制的简单例子.在驱动模块中需要实现struct file_operations的.poll成员.在驱动模块中xxx_poll函数的的作用是将当前进程添加到等待队列中:然后判断事件是否发生,发生则返回POLLIN | POLLRDNORM,否则返回0(可以看看上一章的例子):接下来分析一下 linux 内核中 poll 机制的实现. 二.poll机制分析 1.系统调用 当应用层调用poll函数时,linux发生系统调用(系统调用入口

poll函数和串口设置.DOC

2015.1.24 今天星期六,多云,早晨8:17起床的,今天是来南京起床最迟的一天,因为昨晚睡得有点迟,今天又不用上课,整个人有点放松.收拾好来到教室,教室门没有开,胡明也到了,其他人还在宿舍睡觉,等了10分钟还没有人来开门,就决定出去逛逛,看看南京市有什么好玩的或者特别的.9点没到从鸿运大厦出门,回来的时候10点10分左右,走了一个多小时,百度地图还是有点管用的,起码没有让我迷路.逛了一圈,以前觉得南京算是个大城市,应该比较繁华或者时尚之类的,但是现在完全没有这种感觉,想到以后的工作,我就想

linux内核函数库文件的寻找

linux内核函数的so库文件怎么找呢? 首先还是要产生一个进程的coredump文件的 linux有一个lib-gdb.so库,这个进程的coredump文件中所有load段的最后一个load段中,通过读取二进制文件将最后一个load段读取出来保存lib-gdb.so库文件,这个库文件就是内核函数的库文件. coredump文件头->多个程序头(每一个程序头都会对应一个load段)->通过程序头读取load段

Linux mmap函数简介

一.简介 Linux提供了内存映射函数mmap, 它把文件内容映射到一段内存上(准确说是虚拟内存上), 通过对这段内存的读取和修改, 实现对文件的读取和修改, 先来看一下mmap的函数声明: 头文件: <unistd.h> <sys/mman.h> 原型: void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offsize); 返回值: 成功则返回映射区起始地址, 失败则返回MAP_FAI

动态替换Linux核心函数的原理和实现

转载:https://www.ibm.com/developerworks/cn/linux/l-knldebug/ 动态替换Linux核心函数的原理和实现 在调试Linux核心模块时,有时需要能够实时获取内部某个路径上的某些函数的执行状态,例如查看传入的变量是否是期望的值,以便判断整个执行流程是否依然正常.由于系统运行时的动态性,使得在执行之前无法预先知道在执行路径的什么地方可能出现问题,因此只能在整个路径上增加许多不必要的信息查询点,造成有用的状态信息被淹没,而且这种增加信息输出的方式(一般