使用非阻塞IO的应用程序通常使用Select 和Poll系统调用查询是否可以对设备进行无阻塞的访问。用户程序中用到最多的是select()
int select(int numfds,fd_set*readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout);
fd_set *readfds,fd_set*writefds,fd_set *errorfds 为被监控的读,写,异常文件描述符集合
struct fd_set可以理解为一个集合,这个集合中存放的是文件描述符(file descriptor)
typedef struct {
unsignedlong fds_bits [__FDSET_LONGS];
} __kernel_fd_set;
#define __FDSET_LONGS (__FD_SETSIZE/__NFDBITS)
可以得知fds_bts为一个长度为16的unsigned long类型数组。
对文件描述符集的操作。
1. 清零:FD_ZERO(&rfds);
#define __FD_ZERO(fdsetp) \
(memset(fdsetp, 0, sizeof (*(fd_set *)(fdsetp))))
2. 将文件描述符加入到文件描述符集中
FD_SET(fd, fd_set *set)
#define __FD_SET(fd, fdsetp) \
(((fd_set*)(fdsetp))->fds_bits[(fd) >> 5] |= (1<<((fd) & 31)))
3.将文件描述符从文件描述符集中删除
#define __FD_CLR(fd, fdsetp) \
(((fd_set*)(fdsetp))->fds_bits[(fd) >> 5] &= ~(1<<((fd) & 31)))
4.判断文件描述符是否置位
#define __FD_ISSET(fd, fdsetp) \
((((fd_set*)(fdsetp))->fds_bits[(fd) >> 5] & (1<<((fd) & 31))) !=0)
设备驱动中的poll操作:
返回是否能对设备进行无阻塞的读,写掩码
Unsigned int(int* poll) (struct file* filp,struct poll_table* wait)
Poll函数模板:
Static unsigned int xxx_poll(struct file*filp, poll_table *wait)
{
Unsigned intmask = 0;
Struct xxx_dev*dev = file->private_data;
…
Poll_wait(filp,&dev->r_wait, wait); //把当前进程添加到wait的等待列表中,如果没有它会怎样。
Poll_wait(filp,&dev->w_wait, wait);
If(readable)
{
Mask |= POLLIN | POLLRDNORM;
}
If(writeable)
{
Mask |= POLLOUT| POLLRDNORM;
}
Return mask;
}
typedef void (*poll_queue_proc)(struct file*, wait_queue_head_t *, struct poll_table_struct *);
typedef struct poll_table_struct {
poll_queue_procqproc;
unsignedlong key;
} poll_table;
为什么要有poll_wait函数调用呢,不用可以不?
具体可以查阅:
http://wenku.baidu.com/view/330d42145f0e7cd18425361a.html