Linux设备驱动归纳总结(三):6.poll和select
一、poll函数poll函数可以同时监视多个文件描述符的状态变化。二、select函数select函数也可以用于监视多个文件描述符的状态变化。使用fd_set时。
- 本文目录导读:
- 1、poll函数
- 2、select函数
- 3、poll和select的比较
- 4、总结
在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);
其中,参数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多路复用,在网络编程中得到广泛应用。虽然它们功能相似,但在实际使用中需要根据具体情况选择合适的方法。