最后更新:2022-01-13 06:57
每次循环遍历所有监视对象,找出发生变化的文件描述符。
每次调用select函数时都需要向操作系统传递监视对象信息,实际上select函数是监视套接字变化的函数,而套接字由操作系统管理。
通过“仅向操作系统传递一次监视对象,监视范围或内容发生变化时只通知发生变化的事项。”的方式可以弥补select函数的缺点。
需要操作系统的支持,Linux是epoll,Windows是IOCP。
epoll从Linux2.5.44内核开始引入。
epoll函数优点:
epoll(A, EPOLL_CTL_ADD, B, C);
epoll例程A注册文件描述符B,监视C中事件。
epoll(A, EPOLL_CTL_ADD, B, NULL);
epoll例程A删除文件描述符B。
epfd,epoll例程文件描述符。
op用于指定监视对象的添加、删除、更改等操作。
EPOLL_CTL_ADD:注册文件描述符
EPOLL_CTL_DEL:删除文件描述符(次数事件为NULL)
EPOLL_CTL_MOD:更改文件描述符关注事件
event,关注的事件
EPOLLIN:需要读取数据
EPOLLOUT:输出缓冲为空,可以立即发送数据
EPOLLPRI:收到OOB数据
EPOLLRDHUP:断开连接或半关闭,边缘触发有用
EPOLLERR:发生错误
EPOLLET:边缘触发得到事件通知
EPOLLONESHOT:发生一次事件后,相应文件描述符不在收到事件通知,需要EPOLL_CTL_MOD再次设置事件
echo_epollserver.c
条件触发(Level Trigger)和边缘触发(Edge Trigger)的区别在于发生事件的时间点。
条件触发特性,条件触发方式中,只要输入缓冲有数据就会一直通知该事件,多次注册事件。
边缘触发中输入缓冲收到数据时仅注册1次该事件。
条件触发,满足条件就触发(比如输入缓冲有数据)。
边缘触发,状态变化才触发(比如无缓冲状态变为有缓冲状态)。
epoll默认以条件触发方式工作。
echo_EPLTserver.c
多次输出return epoll_wait
将
clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &addr_size);
后面
event.events=EPOLLIN;
修改为
event.events=EPOLLIN|EPOLLET;
仅输出一次return epoll_wait
select以条件触发方式工作。
read函数发现缓冲中无数据可读时返回-1,同时在errno中保存EAGAIN常量。
边缘触发方式中,仅注册一次事件。
一旦发生输入事件,就应该读取输入缓冲中全部数据。
read返回-1,同时在errno值为EAGAIN,说明无数据可读。
边缘触发方式中,阻塞方式工作的read&write函数可能引起服务器端的长时间停顿,边缘触发方式中一定要采用非阻塞read&write函数。
echo_EPETserver.c
边缘触发相对于条件触发的优点:可以分离接收数据和处理数据的时间点。
从实现模型的角度看,边缘触发更有可能带来高性能,但不能简单地认为只要使用边缘触发就一定能提高速度。
本文由 在线网速测试 整理编辑,转载请注明出处。