Chinaunix首页 | 论坛 | 博客
  • 博客访问: 523400
  • 博文数量: 235
  • 博客积分: 1209
  • 博客等级: 少尉
  • 技术积分: 1417
  • 用 户 组: 普通用户
  • 注册时间: 2011-11-19 19:59
文章分类

全部博文(235)

文章存档

2012年(107)

2011年(128)

分类:

2012-02-14 22:54:14

select系统调用及驱动实现方法


一.系统提供select函数来实现多路复用输入/输出模型。原型:


#include <linux/poll.h>
int select(int maxfd,fd_set *rdset,fd_set *wrset,fd_set *exset,struct timeval *timeout); 

参数maxfd是需要监视的最大的文件描述符值+1;rdset,wrset,exset分别对应于需要检测的可读文件描述符的集合,可写文件描述符的集 合及异常文件描述符的集合。struct timeval结构用于描述一段时间长度,如果在这个时间内,需要监视的描述符没有事件发生则函数返回,返回值为0。 

返回值正整数,表示满足的文件描述符的个数.

返回0,表示超时.

返回-1,且errno为 -EENTIR,表示select在阻塞时被信号中断.

返回-1,其他情况下的错误返回,会设置相应errno.


二.使用select进行I/O复用的方法


1.将需要监控的文件描述符加入文件描述符集合.

  文件描述符集合结构:struct fd_set.内核提供了一些用来操作文件描述符集合:

  FD_ZERO(fd_set *fdset);将指定的文件描述符集清空,在对文件描述符集合进行设置前,必须对其进行初始化,如果不清空,由于在系统分配内存空间后,通常并不作清空处理,所以结果是不可知的。
  

   FD_SET(int fd,fd_set *fdset);用于在文件描述符集合中增加一个新的文件描述符。
  

   FD_CLR(fd_set *fdset);用于在文件描述符集合中删除一个文件描述符。
  

   FD_ISSET(int fd,fd_set *fdset);用于测试指定的文件描述符是否在该集合中。 


2.调用select进行监控.


3.查看文件描述符的集合状态是否发生变化.

  Select在返回之后,如果有满足条件的文件描述符,那么相应的fd_set会发生变化,其中包含的都是满足条件的fd,因此用FD_ISSET来判断某个fd是否满足要求.


三.select系统调用的实现


   select系统调用由驱动的poll方法实现,原型为:

unsigned int poll(struct file *filp,poi_table *wait);

poll 设备方法负责完成:

1.使用poll_wait将等待队列添加到poll_table中.

  void poll_wait(struct file *,wait_queue_head_t *,poll_table *);

2.返回描述设备是否可读或可写的掩码. 

  POLLIN 设备可读

  POLLRDNORM 数据可读

  POLLOUT 设备可写

  POLLWRNORM 数据可写

设备可读一般返回(POLLIN|POLLRDNORM),设备可写一般返回(POLLOUT|POLLWRNORM).


四.POLL工作原理解析


   在设备的poll方法的实现过程中,会发现并没有将进程阻塞的语句,这是因为Poll方法只是做一个登记,真正的阻塞在fs/select.c中的do_select函数.do_select是select系统调用对应的内核函数.do_select根据poll方法返回值来进行判断,如果条件不满足,那么do_select中会调用poll_schedule_timeout将进程设置为可中断睡眠.(待续...)

阅读(870) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~