#include <poll.h>
int poll(struct pollfd fd[], nfds_t nfds, int timeout);
参数:
1)第一个参数:一个结构数组,struct pollfd结构如下:
struct pollfd
{
int fd; //文件描述符
short events; //请求的事件
short revents; //返回的事件
};
events和revents是通过对代表各种事件的标志进行逻辑或运算构建而成的。events包括要监视的事件,poll用已经发生的事件填充revents。poll函数通过在revents中设置标志肌肤POLLHUP、POLLERR和POLLNVAL来反映相关条件的存在。不需要在events中对于这些标志符相关的比特位进行设置。如果fd小于0, 则events字段被忽略,而revents被置为0.标准中没有说明如何处理文件结束。文件结束可以通过revents的标识符POLLHUN或返回0字节的常规读操作来传达。即使POLLIN或POLLRDNORM指出还有数据要读,POLLHUP也可能会被设置。因此,应该在错误检验之前处理正常的读操作。
poll函数的事件标志符值
常量 | 说明 |
POLLIN | 普通或优先级带数据可读 |
POLLRDNORM | 普通数据可读 |
POLLRDBAND | 优先级带数据可读 |
POLLPRI | 高优先级数据可读 |
POLLOUT | 普通数据可写 |
POLLWRNORM | 普通数据可写 |
POLLWRBAND | 优先级带数据可写 |
POLLERR | 发生错误 |
POLLHUP | 发生挂起 |
POLLNVAL | 描述字不是一个打开的文件 |
注意:后三个只能作为描述字的返回结果存储在revents中,而不能作为测试条件用于events中。
2)第二个参数nfds:要监视的描述符的数目。
3)最后一个参数timeout:是一个用毫秒表示的时间,是指定poll在返回前没有接收事件时应该等待的时间。如果 它的值为-1,poll就永远都不会超时。如果整数值为32个比特,那么最大的超时周期大约是30分钟。
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <poll.h>
int main(void)
{
// 读取鼠标
int fd = -1, ret = -1;
char buf[200];
struct pollfd myfds[2] = {0};
fd = open("/dev/input/mouse1", O_RDONLY);
if (fd < 0)
{
perror("open:");
return -1;
}
// 初始化我们的pollfd
myfds[0].fd = 0; // 键盘
myfds[0].events = POLLIN; // 等待读操作
myfds[1].fd = fd; // 鼠标
myfds[1].events = POLLIN; // 等待读操作
ret = poll(myfds, fd+1, 10000);
if (ret < 0)
{
perror("poll: ");
return -1;
}
else if (ret == 0)
{
printf("超时了\n");
}
else
{
// 等到了一路IO,然后去监测到底是哪个IO到了,处理之
if (myfds[0].events == myfds[0].revents)
{
// 这里处理键盘
memset(buf, 0, sizeof(buf));
read(0, buf, 5);
printf("键盘读出的内容是:[%s].\n", buf);
}
if (myfds[1].events == myfds[1].revents)
{
// 这里处理鼠标
memset(buf, 0, sizeof(buf));
read(fd, buf, 50);
printf("鼠标读出的内容是:[%s].\n", buf);
}
}
return 0;
}
总结:select和poll 外部阻塞式,内部非阻塞式自动轮询多路阻塞式IO