Linux之poll机制分析

应用程序访问1个设备文件时可用阻塞/非阻塞方式.如果是使用阻塞方式,则直接调用open()、read()、write(),但是在驱动程序层会判断是否可读/可写,如果不可读/不可写,则将当前进程休眠,直到被唤醒。如果是使用非阻塞方式,就需要采用poll/select机制,而且打开文件时标记文件的访问权限位为O_NONBLOCK。

1 int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); 

FD_CLR(inr fd,fd_set* set);用来清除描述词组set中相关fd 的位

FD_ISSET(int fd,fd_set *set);用来测试描述词组set中相关fd 的位是否为真

FD_SET(int fd,fd_set*set);用来设置描述词组set中相关fd的位

FD_ZERO(fd_set *set);用来清除描述词组set的全部位

如果参数timeout设为:NULL:则表示select()没有timeout,select将一直被阻塞,直到某个文件描述符上发生了事件。0:仅检测描述符集合的状态,然后立即返回,并不等待外部事件的发生。特定的时间值:如果在指定的时间段里没有事件发生,select将超时返回。

1 int poll(struct pollfd *fds, nfds_t nfds, int timeout);这两个函数其实本质类似.

fds 可以传递多个结构体,也就是说可以监测多个驱动设备所产生的事件,只要有一个产生了请求事件,就能立即返回

  struct pollfd {

    int fd; /* 文件描述符 */

    short events; /* 请求的事件类型,监视驱动文件的事件掩码 */

    short revents; /* 驱动文件实际返回的事件 */

  } ;

nfds 监测驱动文件的个数

timeout 超时时间,单位为ms

事件类型events 可以为下列值:

POLLIN 有数据可读

POLLRDNORM 有普通数据可读,等效与POLLIN

POLLPRI 有紧迫数据可读

POLLOUT 写数据不会导致阻塞

POLLER 指定的文件描述符发生错误

POLLHUP 指定的文件描述符挂起事件

POLLNVAL 无效的请求,打不开指定的文件描述符

返回值

有事件发生 返回revents域不为0的文件描述符个数(也就是说事件发生,或者错误报告)

超时 返回0;

失败   返回-1,并设置errno为错误类型

理解select模型:

理解select模型的关键在于理解fd_set,为说明方便,取fd_set长度为1字节,fd_set中的每个bit 可以对应一个文件描述符fd。则1字节长的fd_set最大可以对应8个fd。

(1)执行fd_set set; FD_ZERO(&set);则set用位表示是0000,0000。

(2)若fd=5,执行FD_SET(fd,&set);后set变为0001,0000(第5位置为1)

(3)若再加入fd=2,fd=1,则set变为0001,0011

(4)执行select(6,&set,0,0,0)阻塞等待

(5)若fd=1,fd=2上都发生可读事件,则select返回,此时set变为0000,0011。

注意:没有事件 发生的fd=5被清空。

从内核态理解poll机制

我们从应用程序直接调用poll函数,系统会走以下流程

 1 app:poll
 2 kernel:sys_poll
 3             do_sys_poll
 4                 poll_initwait(&table)
 5                 do_poll(nfds, head, &table, timeout)
 6                         for (;;) {
 7                             for (; pfd != pfd_end; pfd++) {    /* 可以监测多个驱动设备所产生的事件 */
 8                                 if (do_pollfd(pfd, pt)) {
 9                                     count++;
10                                     pt = NULL;
11                                 }
12                                 if (count || !*timeout || signal_pending(current))
13                                     break;
14                                 __timeout = schedule_timeout(__timeout);
15                             }
16                         }
17
18
19 do_pollfd(pfd, pt){
20 ...
21 if (file->f_op && file->f_op->poll)
22     mask = file->f_op->poll(file, pwait);
23     return mask;
24 ...
25 }基于内核源码版本为linux-2.6.22.6

使用poll_initwait(&table),就是将__pollwait设为回调函数,后面会去调用驱动程序的poll函数,poll函数调用pollwait就等于调用__pollwait,将当前进程加入到等待队列中。然后一直在循环,do_pollfd就是去调用驱动程序的poll函数,驱动程序的poll函数,poll函数开始调用pollwait就等于调用__pollwait回调函数,将当前进程加入到等待队列中,以便唤醒休眠后的当前进程。然后返回当前驱动设备的状态(mask).
如果do_pollfd返回的mask为非0,即count非0,就会马上返回,应用程序就可以使用FD_ISSET了解此时设备状态。当然,如果超时或者此进程有其他信号要处理超时,此进程有其他信号要处理,也会马上返回,但是应用程序使用FD_ISSET了解到此时设备状态还是不可用时,又继续轮询。如果do_pollfd返回的mask为0,而且未超时且未有其他信号发生,就会进程调度,让此进程休眠。在前面已经将此进程加入到驱动程序的等待队列中了,如果设备可用时,就会唤醒等待队列中的进程,也就唤醒了此进程,又去poll_initwait(&table).

参考:https://www.cnblogs.com/amanlikethis/p/6915485.html

http://www.cnblogs.com/shihaochangeworld/p/5747490.html

原文地址:https://www.cnblogs.com/hwli/p/9218245.html

时间: 2024-08-08 09:59:33

Linux之poll机制分析的相关文章

linux poll机制分析(二)

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

Linux通信之poll机制分析

poll机制分析 韦东山 2009.12.10 所有的系统调用,基于都可以在它的名字前加上"sys_"前缀,这就是它在内核中对应的函数.比如系统调用open.read.write.poll,与之对应的内核函数为:sys_open.sys_read.sys_write.sys_poll. 一.内核框架: 对于系统调用poll或select,它们对应的内核函数都是sys_poll.分析sys_poll,即可理解poll机制. sys_poll函数位于fs/select.c文件中,代码如下:

linux RCU锁机制分析

openVswitch(OVS)源代码之linux RCU锁机制分析 分类: linux内核  |  标签: 云计算,openVswitch,linux内核,RCU锁机制  |  作者: yuzhihui_no1 相关  |  发布日期 : 2014-10-19  |  热度 : 1044° 前言 本来想继续顺着数据包的处理流程分析upcall调用的,但是发现在分析upcall调用时必须先了解linux中内核和用户空间通信接口Netlink机制,所以就一直耽搁了对upcall的分析.如果对ope

Linux 线程实现机制分析 Linux 线程实现机制分析 Linux 线程模型的比较:LinuxThreads 和 NPTL

Linux 线程实现机制分析 Linux 线程实现机制分析  Linux 线程模型的比较:LinuxThreads 和 NPTL http://www.ibm.com/developerworks/cn/linux/kernel/l-thread/ 自从多线程编程的概念出现在 Linux 中以来,Linux 多线应用的发展总是与两个问题脱不开干系:兼容性.效率.本文从线程模型入手,通过分析目前 Linux 平台上最流行的 LinuxThreads 线程库的实现及其不足,描述了 Linux 社区是

poll机制分析[转]

所有的系统调用,基于都可以在它的名字前加上"sys_"前缀,这就是它在内核中对应的函数.比如系统调用open.read.write.poll,与之对应的内核函数为:sys_open.sys_read.sys_write.sys_poll. 一.内核框架: 对于系统调用poll或select,它们对应的内核函数都是sys_poll.分析sys_poll,即可理解poll机制. sys_poll函数位于fs/select.c文件中,代码如下: asmlinkage long sys_pol

Linux内核NAPI机制分析

转自:http://blog.chinaunix.net/uid-17150-id-2824051.html 简介:NAPI 是 Linux 上采用的一种提高网络处理效率的技术,它的核心概念就是不采用中断的方式读取数据,而代之以首先采用中断唤醒数据接收的服务程序,然后 POLL 的方法来轮询数据.随着网络的接收速度的增加,NIC 触发的中断能做到不断减少,目前 NAPI 技术已经在网卡驱动层和网络层得到了广泛的应用,驱动层次上已经有 E1000 系列网卡,RTL8139 系列网卡,3c50X 系

[转载]Linux 线程实现机制分析

本文转自http://www.ibm.com/developerworks/cn/linux/kernel/l-thread/ 支持原创.尊重原创,分享知识! 自从多线程编程的概念出现在 Linux 中以来,Linux 多线应用的发展总是与两个问题脱不开干系:兼容性.效率.本文从线程模型入手,通过分析目前 Linux 平台上最流行的 LinuxThreads 线程库的实现及其不足,描述了 Linux 社区是如何看待和解决兼容性和效率这两个问题的. 一.基础知识:线程和进程 按照教科书上的定义,进

Linux 线程实现机制分析(转载)

自从多线程编程的概念出现在 Linux 中以来,Linux 多线应用的发展总是与两个问题脱不开干系:兼容性.效率.本文从线程模型入手,通过分析目前 Linux 平台上最流行的 LinuxThreads 线程库的实现及其不足,描述了 Linux 社区是如何看待和解决兼容性和效率这两个问题的. 一.基础知识:线程和进程 按照教科书上的定义,进程是资源管理的最小单位,线程是程序执行的最小单位.在操作系统设计上,从进程演化出线程,最主要的目的就是更好的支持SMP以及减小(进程/线程)上下文切换开销. 无

Linux内核OOM机制分析

一 应用场景描述 线上一台mongos出现OOM情况,于是花点时间想要详细了解Linux内核的OOM机制原理,便于以后再作分析 $ sudo grep mongos /var/log/messages  Apr 10 15:35:38 localhost sz[32066]: [xxxx] check_mongos.sh/ZMODEM: 211 Bytes, 229 BPS Apr 23 14:50:18 localhost sz[5794]: [xxxxx] mongos/ZMODEM: 29