select/poll/epoll 区别 学习笔记

本文对比了select、poll及epoll三种I/O多路复用技术的特点与效率。select采用轮询机制,受文件描述符数量限制;poll改进了文件描述符数量的限制,但仍然存在遍历效率问题;epoll则采用回调机制,适用于大量连接但活跃度不高的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

select和epoll效率差的原因:select是轮询的,而epoll是触发式的,所以epoll的效率高;

select:

原型:

int select(

int nfds, // 本参数忽略,只为与Berkeley套接字兼容

fd_set* readfds, // 可选,指向一组等待可读性检查的套接字的指针  

fd_set* writefds, // 可选,指向一组等待可写性检查的套接字的指针

fd_set* exceptfds, // 可选,指向一组等待错误检查的套接字的指针

const struct timeval* timeout // select等待的最长时间,如果想阻塞则设置为NULL

);

- socket数量(文件描述符更准确一些)限制:该模式可操作的socket数量有FD_SETSIZE(宏),内核默认32*32=1024.Windows默认是64,可通过WinSock2.h修改;

- 操作限制:通过遍历FD_SETSIZE个socket来完成调度,不管哪一个socket是活跃的,都要全部遍历一遍:(如果socket数量小并且均很活跃,那么select效率还是不错的)

- 其他:每次调用都要将fd从用户态拷贝到内核态;

- 说明:无论遍历还是拷贝,这种效率都是线性下降的;

- select小结:

select效率底下是select机制本身决定的,与操作系统无关,任何内核在实现select时都必须做遍历——轮询,才能知道哪些socket是准备好的,这会消耗cpu;

当有一个很大的socket集合时,尽管我们只关心那些活跃的socket,即准备好的、我们可以直接拿过来读或者写操作,但是我们不得不每次都将所有的socket填入到FD_SET中,这也会消耗CPU;

poll:

- socket数量几乎没有限制:该模式下的socket对应的fd列表由一个数组保存,大小不限(默认4K),这个值跟系统的内存关系很大;

- 操作限制:同select

- 其他:同样每次调用都需要将包含所有fd的数组从用户态拷贝到内核态;

- 说明:同select

epoll:

- socket数量无限制:同poll;

- 操作无限制:基于内核提供的反射模式(回调机制),有活跃的socket时,内核访问socket的callback(外部注入),不需要遍历轮询,但是当所有的socket都很活跃的时候,这时候所有的callback都被唤醒,会导致资源的竞争,既然要处理几乎所有的socket,那么,遍历是最简单有效的实现方式——select模型;

- epoll小结:

epoll的试用场景就是有大量的socket,但是活跃不是很高的情况;

// 仅仅是一个简单的,概念上的比较,后续会从代码层面深入理解;

参考:

http://www.cnblogs.com/Anker/p/3265058.html

http://blog.chinaunix.net/uid-20665047-id-3595356.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值