Linux设备驱动归纳总结(三):6.poll和select

一、poll函数poll函数可以同时监视多个文件描述符的状态变化。二、select函数select函数也可以用于监视多个文件描述符的状态变化。使用fd_set时。

在Linux设备驱动中,poll和select是两个非常重要的函数。它们可以用于监视文件描述符的状态变化,从而实现I/O多路复用。本文将对这两个函数进行详细介绍。

一、poll函数

poll函数可以同时监视多个文件描述符的状态变化。其声明如下:

“`c

#include

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

“`

其中,参数fds是一个指向结构体数组的指针,每个结构体都表示一个待监视的文件描述符;nfds表示fds数组中元素的数量;timeout表示超时时间(以毫秒为单位),如果为负数则表示无限等待。

struct pollfd 结构体定义如下:

struct pollfd {

int fd; // 文件描述符

short events; // 等待事件

short revents; // 实际发生了哪些事件

};

events字段用于设置需要等待哪些事件发生,其取值可以是以下几种:

– POLLIN:有数据可读。

– POLLOUT:写操作不会阻塞。

– POLLERR:错误发生。

– POLLHUP:挂起事件。

– POLLRDHUP: 对端关闭连接或者半关闭连接。

revents字段记录实际发生了哪些事件。

使用poll函数时,需要将文件描述符设置为非阻塞模式。如果一个文件描述符上同时发生了多个事件,poll函数只会返回其中的一部分。

二、select函数

select函数也可以用于监视多个文件描述符的状态变化。其声明如下:

#include

int select(int nfds, fd_set *readfds, fd_set *writefds,

fd_set *exceptfds, struct timeval *timeout);

Linux设备驱动归纳总结(三):6.poll和select

其中,参数nfds表示最大的文件描述符加1;readfds、writefds和exceptfds分别表示需要等待哪些事件发生;timeout表示超时时间。

fd_set结构体定义如下:

typedef struct {

unsigned long fds_bits[FD_SETSIZE / (8*sizeof(long))];

} fd_set;

使用fd_set时,需要使用宏FD_ZERO、FD_SET和FD_ISSET进行操作。例如:

fd_set rfds;

struct timeval tv;

FD_ZERO(&rfds);

FD_SET(STDIN_FILENO, &rfds);

tv.tv_sec = 5;

tv.tv_usec = 0;

if (select(STDIN_FILENO+1, &rfds, NULL, NULL, &tv) == -1) {

perror(“select”);

exit(EXIT_FAILURE);

}

if (FD_ISSET(STDIN_FILENO, &rfds)) {

printf(“A key was pressed!n”);

在上面的代码中,首先使用宏FD_ZERO将rfds清零,并使用宏FD_SET将标准输入设置为待监视的文件描述符。然后调用select函数进行等待,在等待期间如果标准输入有数据可读,则调用宏FD_ISSET判断是否有数据可读。

三、poll和select的比较

poll和select都可以用于监视多个文件描述符的状态变化,但是它们有以下几点不同:

– select函数使用fd_set结构体进行操作,而poll函数使用struct pollfd结构体进行操作。

– select函数所能监视的文件描述符数量存在限制(通常为1024),而poll函数没有这个限制。

– poll函数在处理大量文件描述符时速度更快一些。

– 在Linux 2.6之后,poll函数支持动态添加和删除待监视的文件描述符。

四、总结

本文对Linux设备驱动中的两个重要函数——poll和select进行了介绍。这两个函数可以用于实现I/O多路复用,在网络编程中得到广泛应用。虽然它们功能相似,但在实际使用中需要根据具体情况选择合适的方法。