一. select 函数
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select (int n,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *timeout);
FD_CLR(int fd, fd_set *set);
FD_ISSET(int fd, fd_set *set);
FD_SET(int fd, fd_set *set);
FD_ZERO(fd_set *set);
select 函数可以监视文件描述符的三种等待状态:readfds 是否可以无阻塞读数据、writefds 是否可以无阻塞写数据、exceptefds 是否发生文件异常。
n 等于所有集合文件描述符的最大值加1。
fd_set 建立了一个需要监控的文件表述符集合。
timeout 定义了监控的时间限制。
FD_CLR 从set集合中清除fd文件。
FD_ZERO 清空set集合中fd文件。
FD_SET 在set集合中添加fd文件。
FD_ISSET 从set集合中查找fd文件。
二. poll 函数
#include <linux/poll.h>
unsigned int (*poll) (struct file *filp, poll_table *wait);
其中 poll_table 结构定义如下。
/*
* structures and helpers for f_op->poll implementations
*/
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 函数中关键要做两件事:
1: 调用 void poll_wait (struct file *, wait_queue_head_t *, poll_table *)
该函数定义如下
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);
}
可见该函数的作用是将用户进程插入驱动的等待队列。
2:返回bits mask供用户进程查询。
三.运行机理
当用户进程调用的select 函数,首先遍历调用在FD_SET中注册fd的poll函数, 在poll函数中将用户进程插入等待队列,并返回bits mask。用户进程在select函数中检查所的的bits mask。
如果有可用资源则立刻对资源进行操作,操作完毕后,,重新开始遍历。
如果没有可用资源,则将进入休眠,等待资源可用的信号来唤醒。