Linux poll机制
1.用户空间调用(参考 poll(2) - Linux man page)
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
it waits for one of a set of file descriptors to become ready to perform I/O.
The set of file descriptors to be monitored is specified in the fds argument, which is an array of structures of the following form:
struct pollfd {
int fd; /* file descriptor */
short events; /* requested events */
short revents; /* returned events */
};
关于timeout参数的说明:
timeout>0,设置超时时间为timeout
timeout=0,直接返回
timeout<0,无限长超时时间
返回值说明:
On success, a positive number is returned; this is the number of structures which have nonzero revents fields (in other words, those descriptors with events or errors reported).
A value of 0 indicates that the call timed out and no file descriptors were ready. On error, -1 is returned, and errno is set appropriately.
2.内核调用
asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds,long timeout_msecs)
-->ret = do_sys_poll(ufds, nfds, &timeout);
-->struct poll_wqueues table;
-->poll_initwait(&table);
-->init_poll_funcptr(&pwq->pt, __pollwait);
-->把ufds指向的用户空间数据拷贝到内核空间,由poll_list结构体保存
-->fdcount = do_poll(nfds, head, &table, timeout);
for (;;) {
-->set_current_state(TASK_INTERRUPTIBLE);
-->for (walk = list; walk != NULL; walk = walk->next) //遍历poll_list结构中的pollfd结构
-->do_pollfd(pfd, pt)
-->if (file->f_op && file->f_op->poll) //驱动中的poll函数
--> void __pollwait(struct file *filp, wait_queue_head_t *wait_address,poll_table *p)
-->struct poll_table_entry *entry = poll_get_entry(p);
-->entry->filp = filp;
-->entry->wait_address = wait_address;
-->init_waitqueue_entry(&entry->wait, current);
-->add_wait_queue(wait_address, &entry->wait);//加入等待队列头
-->return mask;//返回设备是否可读写状态
-->if (count || !*timeout || signal_pending(current))
break;//设备可读写,超时时间到,有信号中断三种情况都返回
-->__timeout = schedule_timeout(__timeout);//进程调度,休眠
}
//唤醒后返回
-->__set_current_state(TASK_RUNNING);
-->return count;
-->把poll_list结构体保存的pollfd.revents返回给用户空间的ufds数组
-->poll_freewait(&table);//释放poll_table_entry中的等待队列
3.相关结构体都在fs/select.c,include/linux/poll.h
poll_wqueues是最关键的一个结构体,
struct poll_wqueues {
poll_table pt;
struct poll_table_page * table;
int error;
int inline_index;
struct poll_table_entry inline_entries[N_INLINE_POLL_ENTRIES];
};
poll_table结构体只包含一个函数指针,初始化时指向
void __pollwait(struct file *filp, wait_queue_head_t *wait_address,poll_table *p)
typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_table_struct *);
typedef struct poll_table_struct {
poll_queue_proc qproc;
} poll_table;
poll_table_page就是包含poll_table_entry结构的链表,作用与inline_entries[N]相同,检测文件数少的时候用不到这个结构
struct poll_table_page {
struct poll_table_page * next;
struct poll_table_entry * entry;
struct poll_table_entry entries[];
};
poll_table_entry包含文件指针,等待队列及等待队列头
struct poll_table_entry {
struct file * filp;
wait_queue_t wait;
wait_queue_head_t * wait_address;
};
4.操作
poll_wqueues初始化
static inline void init_poll_funcptr(poll_table *pt, poll_queue_proc qproc)
{
pt->qproc = qproc;
}
void poll_initwait(struct poll_wqueues *pwq)
{
init_poll_funcptr(&pwq->pt, __pollwait);
pwq->error = ;
pwq->table = NULL;
pwq->inline_index = ;
}
那么poll_table结构中的函数什么时候使用及干什么呢?
我们自己在驱动中的poll函数中会调用poll_wait()函数
static unsigned forth_drv_poll(struct file *file, poll_table *wait)
{
unsigned int mask = ;
poll_wait(file, &button_waitq, wait); // 不会立即休眠 if (ev_press)
mask |= POLLIN | POLLRDNORM; return mask;
}
而poll_wait()函数最终会调用__pollwait()函数
static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
{
if (p && wait_address)
p->qproc(filp, wait_address, p);
}
/* Add a new entry */
static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
poll_table *p)
{
struct poll_table_entry *entry = poll_get_entry(p);
if (!entry)
return;
get_file(filp);
entry->filp = filp;
entry->wait_address = wait_address; //即forth_drv_poll中传入的button_waitq等待队列头
init_waitqueue_entry(&entry->wait, current);
add_wait_queue(wait_address, &entry->wait);
}
Linux poll机制的更多相关文章
- [转载] Linux poll机制
原地址:http://hongwazi.blog.163.com/blog/#m=0&t=3&c=poll poll的是一种查询的方式,英文解释 :民意调查 函数原型:int poll ...
- 嵌入式Linux驱动学习之路(十二)按键驱动-poll机制
实现的功能是在读取按键信息的时候,如果没有产生按键,则程序休眠在read函数中,利用poll机制,可以在没有退出的情况下让程序自动退出. 下面的程序就是在读取按键信息的时候,如果5000ms内没有按键 ...
- Linux学习 :中断处理机制 & poll机制
中断是指在CPU正常运行期间,由于内外部事件或由程序预先安排的事件引起的CPU暂时停止正在运行的程序,转而为该内部或外部事件或预先安排的事件服务 的程序中去,服务完毕后再返回去继续运行被暂时中断的程序 ...
- linux驱动编写之poll机制
一.概念 1.poll情景描述 以按键驱动为例进行说明,用阻塞的方式打开按键驱动文件/dev/buttons,应用程序使用read()函数来读取按键的键值.这样做的效果是:如果有按键按下了,调用该re ...
- Linux驱动之poll机制的理解与简单使用
之前在Linux驱动之按键驱动编写(中断方式)中编写的驱动程序,如果没有按键按下.read函数是永远没有返回值的,现在想要做到即使没有按键按下,在一定时间之后也会有返回值.要做到这种功能,可以使用po ...
- Linux之poll机制分析
应用程序访问1个设备文件时可用阻塞/非阻塞方式.如果是使用阻塞方式,则直接调用open().read().write(),但是在驱动程序层会判断是否可读/可写,如果不可读/不可写,则将当前进程休眠,直 ...
- linux IO多路复用POLL机制深入分析
POLL机制的作用这里就不进行介绍,根据linux man手册,解释为在一个文件描述符上等待某个事件.按照抽象一点的理解,当某个事件被触发(条件被满足),文件描述符变为有状态,那么用户空间可以根据此进 ...
- linux字符驱动之poll机制按键驱动
在上一节中,我们讲解了如何自动创建设备节点,实现一个中断方式的按键驱动.虽然中断式的驱动,效率是蛮高的,但是大家有没有发现,应用程序的死循环里的读函数是一直在读的:在实际的应用场所里,有没有那么一种情 ...
- 【原创】Linux select/poll机制原理分析
前言 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 1. 概述 Linux系统 ...
随机推荐
- Zynq7000开发系列-4(新:Xilinx交叉编译环境搭建)
一.前言 本来上一篇文章已经讲了Xilinx交叉编译环境的搭建,但是我在后续的使用中发现:使用2011年版本的交叉编译链编译OpenCV 3.1.0时出现错误: 网络搜索一番,查明是交叉编译链的问题 ...
- HDU3853(期望)
题目很水了,但是原地打转的点……虽然不难想到这个坑,但是从数学的角度来讲期望不应该算正无穷嘛……为什么算0啊? ; ; int R, C; struct gird { db ori, right, d ...
- python学习之j进程和线程:
每个进程至少有一个线程,python因为每个线程都共用一个GIL全局锁(同时只能运行一个线程),所以不能用多线程(除非重新写C解释器),但是多进程的GIL锁各自独立可多进程. 进程与线程的区别在于一个 ...
- [已读]用Angularjs开发下一代web应用
屯了很久了,貌似是国内出现的第一本讲angularjs的书...上上周看完的时候,angular2都要出来了...angular的双向绑定很赞,因为之前公司后台系统我都用tmodjs做,模板语法什么的 ...
- 阻止微信浏览器下拉滑动效果(ios11.3 橡皮筋效果)
在升级到 ios11.3 系统后,发现之前阻止页面滚动的代码e.preventDefault代码失效了.于是自己折腾了一番,找到了解决办法,分享给大家. 一.前言 浏览器在移动端有一个默认触摸滚动的效 ...
- Oracle查询排序asc/desc 多列 order by
查询结果的排序 显示EMP表中不同的部门编号. 如果要在查询的同时排序显示结果,可以使用如下的语句: SELECT 字段列表 FROM 表名 WHERE 条件 ORDER BY 字段名1 [ASC|D ...
- IE兼容只读模式
表单input具有只读模式属性,一般来说,一般的浏览器都支持该属性,即readyonly,但IE不支持,只能寻找其兼容性. 第一种:unselectable='on' <input id=&qu ...
- CSS-学习笔记五
1. 权重: 内联:A ID:B Class:C 标签:D 继承:0 2. 文字阴影text-shadow 3. 文字缩进text-index 4. 文本换行 5. 文本溢出 6. 圆角 ...
- (二)mybaits之ORM模型
前言:为什么还没有进入到mybatis的学习呢?因为mybatis框架的核心思想就是ORM模型,所以好好了解一下ORM模型是有必要哒. ORM模型 ORM(Object Relational Ma ...
- (十一)maven之安装nexus私服
安装nexus私服 前面的文章中对项目引入jar依赖包的时候,maven一般先是在本地仓库找对应版本的jar依赖包,如果在本地仓库中找不到,就上中央仓库中下载到本地仓库. 然而maven默认提供的中央 ...