int poll(struct pollfd* fds, nfds_t nfds, int timeout);
fds:事件结构数组,poll函数是通过用户传入的事件结构数组进行监控的,也是轮询监控的方式
如果要监控一个文件描述符,则组织一个事件结构,传递给poll
如果要监控多个文件描述符,则组织多个事件结构,放到数组当中,传递给poll
时间结构:struct pollfd{…}
struct pollfd { int fd; short events; short revents; }
fd:待要监控的文件描述符
events:关心当中文件描述符产生什么事件(可读、可写、异常)
POLLIN:可读事件
POLLOUT:可写事件
如果既关心可读事件也关心可写时间,则将POLLIN | POLLOUT
revents:在poll监控文件描述符的时候,真实产生的事件
poll在监控的过程当中,文件描述符发生了什么事件,就将该事件放到revents当中
在定义pollfd事件结构体的时候,不需要用户进行初始化,由poll函数进行初始化
小结:
(1)poll函数引入了事件结构数组的方式,对需要内核监控的文件描述符个数是没有限制了。
(2)poll在监控事件结构数组的时候,也是采用轮询遍历的方式进行监控,随着监控的事件结构(文件描述符)的增多,监控轮询效率下降。
(3)用户如果关心一个文件描述符的多种事件(可读、可写、异常),可以直接在同一个事件结构的结构体当中表示,不需要像select一样,添加到不同的事件集合当中去。
nfds:事件结构数组当中有效元素的个数,用来指导poll函数,轮询遍历的范围
eg:struct pollfd arr[10];
arr[0].fd = 0;
arr[0].events = POLLIN;
则:nfds = 1;
timeout:超时时间
> 0 :带有超时时间的监控,单位:毫秒
0 :非阻塞的监控方式
< 0 :阻塞监控的方式
注意区分poll与select的超时时间的传参方式
select的超时时间参数是struct timeval * timeout,需要传入timeval结构体地址。
poll的超时时间参数是int timeout,只需要传入数字即可。
返回值:> 0 :监控成功,返回就绪的文件描述符个数
== 0 :监控超时
< 0 :监控出错
优点:
(1)引入了事件结构的方式,用户不需要将关心的事件添加到不同的事件集合当中去。
(2)引用了事件结构的方式,对监控的文件描述符的个数不再限制。
(3)针对和select对比之后,当一次监控成功之后,下一次再次进行监控的时候,不需要重新添加。
缺点:
(1)与select一样也是采用轮询遍历的策略,随着监控的文件描述符增多,轮询效率会下降。
(2)poll不支持跨平台,只能在linux操作系统下使用
(3)在调用poll函数的时候,会将用户组织的事件结构数组,拷贝到内核空间,监控成功之后,会将事件结构数组从内核空间拷贝到用户空间,这个举动比较耗费性能。
#include <stdio.h> #include <unistd.h> #include <poll.h> //阻塞 监控 0 号文件描述符 int main() { struct pollfd pf; pf.fd = 0; pf.events = POLLIN; // 关心可读事件 poll(&pf, 1, -1); // <0 是阻塞监控 char buf[1024] = {0}; read(0, buf, sizeof(buf) - 1); printf("buf is : %s\n", buf); return 0; }
#include <stdio.h> #include <unistd.h> #include <poll.h> //非阻塞监控 0 号文件描述符 int main() { struct pollfd pf; pf.fd = 0; pf.events = POLLIN; while(1) { int ret = poll(&pf, 1, 0); //0表示非阻塞 if(ret < 0) { perror("poll"); return 0; } else if(ret == 0) { printf("poll timeout\n"); sleep(1); continue; //超时,继续监控 } char buf[1024] = {0}; read(0, buf, sizeof(buf) - 1); printf("buf is : %s\n", buf); } return 0; }
#include <stdio.h> #include <unistd.h> #include <poll.h> //超时时间监控0号文件描述符 int main() { struct pollfd pf; pf.fd = 0; pf.events = POLLIN; while(1) { int ret = poll(&pf, 1, 1); if(ret < 0) { perror("poll"); return 0; } else if(ret == 0) { printf("poll timeout\n"); sleep(1); continue; } char buf[1024] = {0}; read(0, buf, sizeof(buf) - 1); printf("buf is :%s\n", buf); } return 0; }