poll与epoll
在linux中,IO多路转接模型,除了select模型可以用,还有poll和epoll两种模型,对于 poll模型现在基本上不用了。
poll模型:
1.流程:
1.用户定义了一个描述符的事件结构体数组,将需要监控的描述符以及 对应的事件信息添加到数组中去。
2.调用poll函数,将有效的节点拷贝到内核中进行监控,有描述符就绪或者等待时间超时的时候返回,返回时每个节点revents成员保存实际的就绪的事件,没有就为0。
3.调用返回,遍历数组,根据每个节点的revents成员来进行判断是否有就绪的描述符。
2.接口:
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
fds:事件结构体数组的首地址。
nfds:数组中有效节点的个数。
timeout:等待的超时时间,
返回值为就绪事件的个数,小于0表示出错,
struct pollfd {
int fd; /* file descriptor */ 监控的描述符
short events; /* requested events */ 监控的事件
short revents; /* returned events */ 就绪的事件
};
3.优缺点:
优点:1.监控的描述符数量没有上限。
2.采用了事件结构的方式监控,简化了多种集合监控的操作流程。
缺点:1.无法跨平台操作。
2.需要每次将要监控的描述符拷贝到内核中去。
3.监控的时候也是轮询的方式,会随着描述符的增加,而使得性能降低。
4.返回的不是就绪的事件,也需要程序员去轮询遍历,找到就绪的事件,然后进行处理。
4.简单的实现:
只监控了可读事件的发生:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <poll.h>
#define MAXFD 10
int socket_create();
void fds_init(struct pollfd fds[]);
void fds_add(struct pollfd fds[], int fd);
void fds_del(struct pollfd fds[], int fd);
int main()
{
int sockfd = socket_create();
assert( sockfd != -1 );
struct pollfd fds[MAXFD];//描述符的结构体数组
fds_init(fds);
fds_add(fds,sockfd);//将监控描述符添加到数组中去
while( 1 )
{
int n = poll(fds,MAXFD,5000);//开始监控
if ( n == -1 ) //出错
{
perror("poll error");
}
else if ( n