linux的poll机制,深入理解linux内核poll机制

深入理解linux内核poll机制

前言:以下内容,部分参考网络资料

poll机制实现的是多路io转接,简单讲就是多个文件进行监控,对应到应用层是select函数

#include int select (int maxfdp1, fd_set *restict readfds, fd_set *restrict writefds,/

fd_set *restrict expectfds, struct timeval *restrict tvptr);

参数:

maxfdp1:文件描述符的范围,比待检测的最大文件描述符大1

readfds:被读监控的文件描述符集

writefds:被写监控的文件描述符集

expectfds:被异常监控的文件描述符集

tvptr:愿意等待的时间

struct timeval {

long tv_sec;

long tv_usec;

};

等待时间可取的值有三种:

1. tvptr = 0; 等待时间为0,无论文件是否满足要求,都会立即返回

2. tvptr = NULL; 等待时间为无限长,一直到有某个文件满足要求,返回一个正数

3. tvptr = time; time为正数,等待时间time到了以后,若没有文件满足要求,也要返回

select函数返回值:

1.返回一个正数,表示满足要求的文件描述符的个数

2.返回0,表示时间到了任然没有满足条件的文件描述符

3.返回-1,被某个信号中断,或者是出错

文件描述符集的概念

readfds、writefds和expectfds是指向描述符集的指针。这三个描述符集说明了我们关系的可读、可写或处于异常

条件的各个描述符。每个描述符集放在一个fd_set数据类型中。

每个被监控的文件描述符占fd_set数据类型的一位,如图

系统提供4个宏对文件描述符进行操作:

1. void FD_SET(int fd, fd_set *fdset)

将文件描述符添加到文件描述符集fd_set中

2. void FD_CLR(int fd, fd_set *fdset)

将文件描述符从fd_set中清除

3. void FD_ZERO(fd_set *fdset)

将文件描述符集fdset清空

3. void FD_ISSET(int fd, fd_set *fdset)

select函数返回后判断某个文件fd是否发生变化

应用层select函数使用方法:

fd_set fds;

int fd1,fd2;

FD_ZERO(&fds); //清空集合

FD_SET(fd1,&fds); //设置描述符

FD_SET(fd2,&fds); //设置描述符

maxfdp=fd1+1; //描述符最大值加1,假设fd1>fd2

switch(select(maxfdp,&fds,NULL,NULL,&timeout)) {

case -1: exit(-1);break; //select错误,退出程序

case 0: break;

default:

if(FD_ISSET(fd1,&fds)){

//...

} //测试fd1是否可读

}

==============================================================================

下面介绍一下内核空间,驱动中poll函数的实现

这个poll函数不是应用层的poll函数,而是在file_operations中的poll函数

以下内核代码基于 linux 3.8 内核

unsigned int (*poll)(struct file *filp, poll_table *wait)

参数:

struct file *filp : 驱动的设备文件符

poll_table *wait : 用来初始化等待队列,后面将分析

该函数的作用有两个:

一是将等待队列添加到poll_table中,第二个是返回可读可写的掩码

POLLIN         有数据可读。

POLLRDNORM       有普通数据可读。

POLLRDBAND      有优先数据可读。

POLLPRI         有紧迫数据可读。

POLLOUT            写数据不会导致阻塞。

POLLWRNORM       写普通数据不会导致阻塞。

POLLWRBAND        写优先数据不会导致阻塞。

POLLMSGSIGPOLL     消息可用。

此外,revents域中还可能返回下列事件:

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

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

POLLNVAL  指定的文件描述符非法。

设备可读通常返回(POLLIN|POLLRDNORM)

设备可写通常返回(POLLOUT|POLLWRNORM)

poll函数编写框架:

static unsigned int XXX_poll(struct file *filp, poll_table *wait)

{

unsigned int mask = 0;

struct XXX_dev *dev = filp->private_data; //获得设备结构指针

...

poll_wait(filp, &dev->r_wait, wait); //加读等待对列头

poll_wait(filp ,&dev->w_wait, wait); //加写等待队列头

if(...)//可读

mask |= POLLIN | POLLRDNORM; //标识数据可获得

if(...)//可写

mask |= POLLOUT | POLLRDNORM; //标识数据可写入

..

return mask;

}===============================================================================

接下来分析一下具体实现细节

从应用层的select是如何调用到内核poll,并且如何实现阻塞,如何实现唤醒

先到这里,改天继续。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值