一开始学习poll、select、epoll这几个API的时候,知道了poll和select是轮询方式,epoll是通过回调的方式,当监听的IO数量过多时,poll和select的效率会很低,而epoll仍然保持着高效
虽然知道是这么回事,但心里还是有点空荡荡的感觉,所以分析了一遍内核源码,背景源码之前,了无密码,哈哈,在这里分享出来,希望对大家有所帮助
本文先讲解一下如何在应用层使用poll,然后再深入内核源码分析poll机制
poll应用程序编写
poll可以监听多个文件描述符,直到条件满足或超时的时候,就会返回
- poll函数原型
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
fds:这是一个数组,每一个数组元素表示要监听的文件描述符以及相应的事件
nfds:数组的个数
timeout:超时时间
放回值:成功放回准备好的事件个数,超时放回0,出错放回-1
- struct pollfd结构体
struct pollfd {
int fd; //要监听的文件描述符
short events; //要监听的事件
short revents; //放回结果
};
对于events和revents部分取值如下
POLLIN //可读
POLLOUT //可写
demo
下面这个程序使用poll监听标准输入,知道标准输入可读时,就会返回打印内容
#include <stdio.h>
#include <poll.h>
#include <string.h>
#define MAX_FD 100
int main(int argc, char* argv[])
{
struct pollfd fds[MAX_FD];
int nfds;
char buf[1024];
int len;
int i;
memset(fds, 0, sizeof(fds));
fds[0].fd = 0; //标准输入
fds[0].events = POLLIN; //可读
while(1)
{
nfds = poll(fds, MAX_FD, -1); //阻塞等待
if(nfds < 0)
{
printf("poll err.\n");
return -1;
}
for(i = 0; i < MAX_FD; i++)
{
if(fds[i].revents | POLLIN) //可达
{
len = read(fds[i].fd, buf, 1024);
if(len < 0)
{
printf("read err.\n");
return -1;
}
buf[len] = '\0';
printf("read buf: %s\n", buf);
}
}
}
return 0;
}