|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
本篇文章是对select、poll、epoll之间的区别进行了详细的分析介绍。需要的朋友参考下7 p! g2 }; D( _
6 Q3 d4 W9 u0 G% i8 N5 k+ \0 q/ R+ s/ H" V s
" p& B6 g9 Q) _) D8 _" l( {. y! u$ }# p1 |: h$ }$ }) v3 f
linux提供了select、poll、epoll接口来实现IO复用,三者的原型如下所示,本文从参数、实现、性能等方面对三者进行对比。& W, c" j8 V' y
" x7 _/ |8 M) {, ~2 M9 ^
7 t4 l5 J* e* [7 B% N/ L& A) G4 Z' O' B代码如下:
/ `& W+ O( I+ Q5 x/ g, I
! j0 f# w \/ d. r3 W( c# B& G9 a- int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
- int poll(struct pollfd *fds, nfds_t nfds, int timeout);
- int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);# m6 i2 r7 n% G+ ?' r' z4 Z
N9 N- f' T' z% T
, z( ?/ g; Q7 X
select、poll、epoll_wait参数及实现对比9 U; o7 M/ j$ V# C( n
8 W& r9 d+ z+ D1 M8 k; `- r( S$ e
1.select的第一个参数nfds为fdset集合中最大描述符值加1,fdset是一个位数组,其大小限制为__FD_SETSIZE(1024),位数组的每一位代表其对应的描述符是否需要被检查。( @5 }: x1 M% _' w/ }+ n9 t
& ]! [5 O' E5 I! T5 q8 b% j1 V
select的第二三四个参数表示需要关注读、写、错误事件的文件描述符位数组,这些参数既是输入参数也是输出参数,可能会被内核修改用于标示哪些描述符上发生了关注的事件。所以每次调用select前都需要重新初始化fdset。$ Z$ @9 ?5 [% @' U8 C( M2 z: z
" |/ l$ T3 X+ D; L/ _timeout参数为超时时间,该结构会被内核修改,其值为超时剩余的时间。
% {8 _+ ~7 f7 [1 I% t
/ \" s$ J9 Y2 H0 c% S4 S4 Xselect对应于内核中的sys_select调用,sys_select首先将第二三四个参数指向的fd_set拷贝到内核,然后对每个被SET的描述符调用进行poll,并记录在临时结果中(fdset),如果有事件发生,select会将临时结果写到用户空间并返回;当轮询一遍后没有任何事件发生时,如果指定了超时时间,则select会睡眠到超时,睡眠结束后再进行一次轮询,并将临时结果写到用户空间,然后返回。
0 M- r. M9 ~& f/ x( {% |. u6 ^) O
( H) u( F. Z6 ]$ {! t, Q2 Eselect返回后,需要逐一检查关注的描述符是否被SET(事件是否发生)。$ {! T' T: b2 n( `4 M9 \
+ B+ e" g4 E9 n6 a3 ? H0 g2.poll与select不同,通过一个pollfd数组向内核传递需要关注的事件,故没有描述符个数的限制,pollfd中的events字段和revents分别用于标示关注的事件和发生的事件,故pollfd数组只需要被初始化一次。9 U% F* f8 V5 B. `& I+ Y3 `7 Z' Z
# q! R8 e4 S3 T0 o0 g3 b
poll的实现机制与select类似,其对应内核中的sys_poll,只不过poll向内核传递pollfd数组,然后对pollfd中的每个描述符进行poll,相比处理fdset来说,poll效率更高。
1 n* G1 Y5 I& y0 j
@7 ?0 p" W2 R# f& _7 o; E2 Spoll返回后,需要对pollfd中的每个元素检查其revents值,来得指事件是否发生。
9 n# i" Y4 K3 D; P" M4 |! K* [ g0 L$ M1 u) N
3.epoll通过epoll_create创建一个用于epoll轮询的描述符,通过epoll_ctl添加/修改/删除事件,通过epoll_wait检查事件,epoll_wait的第二个参数用于存放结果。
( u% E/ \0 t6 V Q( h5 c2 J; D& n' n
0 H: i2 b' q2 E, u' u7 f/ d5 _+ e# y5 l& W" D# D0 X: R
i9 g: ?+ w& h) t$ u; C" q |
|