使用非阻塞I/O的应用程序通常会使用select()和poll()系统调用查询是否可以对设备进行无阻塞的访问。
l 应用程序中的轮询编程
int select(int numfds,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *timeout);
numfds,需要检查的文件描述符的最大值加1。
readfds,writefds,exceptfds分别是读,写和异常处理的文件描述符集。
timeout,指向struct timeval的指针。select()在等待timeout时间后若没有文件描述符准备好则返回。
n timeout为0,不管是否有文件满足要求,都立刻返回,无文件满足要求返回0,有文件满足要示返回一个正值。
n timeout为NULL,select将阻塞进程,直到某个文件满足要求。
n timeout为正整数,就是等待的最长时间。
select正常情况下返回满足要求的文件描述符的个数。
若被中断,它返回-1,并设置相应的errno为EINTR.
struct timeval
{
int tv_sec;
int tv_usec;
}
清除一个文件描述符集
FD_ZERO(fd_set *set)
将一个文件描述符加入文件描述符集中
FD_SET(int fd,fd_set *set)
将一个文件描述符从文件描述符集中清除
FD_CLR(int fd,fd_set *set)
判断一个文件描述符是否在描述符集中发生了变化,若变化就返回1
FD_ISSET(int fd,fd_set *set)
l 设备驱动中的轮询编程
unsigned int(*poll)(struct file *filp ,struct poll_table *wait);
返回:是否能对设备进行无阻塞读写的访问的掩码
向poll_table注册等待队列的poll_wait()函数
void poll_wait(struct file *filp,wait_queue_head_t *queue,poll_table *wait);
poll_wait这个函数不会引起阻塞。poll_wait函数将当前进程添加到wait参数指定的等待列表(poll_table)中。poll函数应返回设备资源可获取的状态,即POLLIN,POLLOUT,POLLPRI,POLLERR,POLLNVAL,每个宏代表设备的一种状态。POLLIN,可以无阻塞地读,POLLOUT,可以无阻塞地写。
l select与poll的使用
1.select
a.在应用程序中定义读,写和异常处理的文件描述符集
如fd_set rfds,wfds
b.以非阻塞方式打开设备
fd=open("/dev/globalfifo",O_RDONLY | O_NONBLOCK);
c.清空文件描述符集
FD_ZERO(&rfds)
d.添加文件描述符集
FD_SET(fd,&rfds)
e.监控变化做相应处理
if(FD_ISSET(fd,&rfds))
{……}
2.poll
f.在文件操作函数中,调用poll_wait()函数,将等待队列头代表的等待队列加入等待列表(poll_table)中
当然在设备结构中,需要定义队列头,在模块初始中,初始化等待队列头。
poll_wait(filp,r_wait,wait);
h.然后根据条件返回掩码
mask |= POLLIN|POLLRDNORM(数据可获得)
mask |= POLLOUT|POLLWRNORM(数据可写入)