监听集合没无动静,如果没有动静就阻塞,如果有动静就成功返回,返回值为集合中有动静的fd的数量。
poll 函数原型
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
参数:
fds:这个参数写为struct pollfd fds[ ] 更好理解,第一个参数要求传递一个 struct poll fd 结构体数组。这个数组就相当于select的文件描述符集合,只不过select是使用fd_set来定义的,而poll的集合是一个数组。
struct pollfd的成员:
struct pollfd
{
int fd; :文件描述符
short events; :设置我们希望发生的事件,比如读事件,这个需要我们自己设置
short revents; :实际发生的事件,比如读事件,由poll机制自己设置
};
events 说明
1、POLLIN 普通或优先级带数据可读
2、POLLRDNORM 普通数据可读
3、POLLRDBAND 优先级带数据可读
4、POLLPRI高优先级数据可读
5、POLLOUT普通数据可写
6、POLLWRNORM 普通数据可写
7、POLLWRBAND 优先级带数据可写
8、POLLERR发生错误
9、POLLHUP发生挂起
10、POLLNVAL 描述字不是一个打开的文件
poll 监听时如果没有动静就阻塞,有动静就不再阻塞,返回有动静的fd的数量。
如何知道是那些fd有动静?
如果文件描述符“发生的事件”==“实际事件”,就说明希望的事件来了,就是对fd进行相应的“读或写”操作。
nfds:数组的元素个数。
timeout:超时时间,如果写的是
-1:不设置超时,如果集合没有动静就一直阻塞下去,直到poll函数被信号中断(唤醒)或者集合有动静为止
非-1值:比如3000(3000微妙),表示将超时时间设置为3秒也就是说poll超时时间的单位时微妙。
返回值:
返回-1:说明函数调用失败,errno被设置。
如果是被信号中断从而导致出错返回-1时,errno被设置为EINTR,
如果不想被中断,要么重启poll的调用,要么忽略或者屏蔽这些信号。
0:超时时间到,而且没有文件描述符有动静。
大于0:返回有响应的文件描述符的数量。
demo代码: 同时读键盘和鼠标
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <poll.h>
int main(int argc, char const *argv[])
{
int fd;
if ((fd = open("/dev/input/mouse0", O_RDWR | O_CREAT, 0655)) < 0)
{
perror("open file error!");
exit(1);
}
struct pollfd fds[2];
fds[0].fd = 0;
fds[0].events = POLLIN;
fds[1].fd = fd;
fds[1].events = POLLIN;
while (1)
{
int ret = poll(fds, 2, -1);
for (int i = 0; i < 2; i++)
{
if (fds[i].events == fds[i].revents)
{
if (fds[i].fd == 0)
{
char buffer[1024];
read(fds[i].fd, buffer, sizeof(buffer));
printf("buffer = %s\n", buffer);
}
else if (fds[i].fd == fd)
{
int cor;
read(fds[i].fd, &cor, sizeof(cor));
printf("cor = %d\n", cor);
}
if (--ret == 0)
{
break;
}
}
}
}
return 0;
}
执行结果:
root@GodFather:/home/superlan/C_Language/advanced_IO_operation# ./a.out
cor = 8486696
cor = 8480552
cor = 12255272
cor = 520
cor = 264
hello
buffer = hello
^C
root@GodFather:/home/superlan/C_Language/advanced_IO_operation#
poll 的优缺点
解决 select 监听文件描述符受限的问题,通过采用链表的方式保存文件描述符
优点
poll 没有最大文件描述符限制(使用链表的方式存储 fd)
缺点:
因为无法获取具体哪个文件描述符发生变化,只能进行全盘轮询,随着监听的文件描述符增多,效率下降;
所监听的文件描述符都必须从用户空间传入内核空间进行监听,涉及到大量的数据拷贝,效率低。