您的位置:首页 > 运维架构 > Linux

Linux高级文件操作 -4

2016-10-16 10:01 211 查看

比较poll()和select()

超时timeout, poll()具有毫秒级别的精度,而select()具有微秒级别的精度,实际上,这个差别几乎没有任何意义,因为它们到微秒时候都不是很精确。

select()时候,内核必须检查所有在0到numfds - 1之间的文件描述符,以发现应用程序是否对文件描述符所对应的I/O时间感兴趣。对于打开大量文件的应用程序,内核要检查哪个文件描述符是它感兴趣的,这将引起大量的浪费。

对于select()而言文件描述符的集合是一个位图,对poll()而言是作为一个列表传送到内核的,相对于简单检查的strcut pollfd,需要复杂检查和设置fd_set数据结构的位操作先得效率更低一点。

因为内核更新了传送到的select()的数据结构,每次需要调用select()的时候,应用程序都必须重置这些数据结构;但是使用poll()内核传递的结果值限于revents成员,避免了每次调用的重置操作。

在进程增加文件描述符的数量时,使用一个fd_set一样的集合的结构不具有很好的伸缩性。因为它是静态大小(不是动态分配),不能随着应用程序的需要(或者内核的能力)而增加或者减少。在Linux下,fd_set中文件描述符的最大数量可是1023。如果一直增加更多的文件描述符集合时,将无法使用select()。

select()仅有的优点就是,对于旧的系统来说具有更好的可移植性。在现实中使用select()的,能体现更好的维护现有的代码库。

select()更第效率;

/* select-vs-poll.c - Compares the performance of \codefn{select()} and \codefn{poll()} */

#include <fcntl.h>
#include <stdio.h>
#include <sys/poll.h>
#include <sys/select.h>
#include <sys/signal.h>
#include <unistd.h>

int gotAlarm;

void catch(int sig) {
gotAlarm = 1;
}

#define HIGH_FD 1000

int main(int argc, const char ** argv) {
int devZero;
int count;
fd_set selectFds;
struct pollfd pollFds;

devZero = open("/dev/zero", O_RDONLY);
dup2(devZero, HIGH_FD);

/* use a signal to know when time's up */
signal(SIGALRM, catch);

gotAlarm = 0;
count = 0;
alarm(1);
while (!gotAlarm) {
FD_ZERO(&selectFds);
FD_SET(HIGH_FD, &selectFds);

select(HIGH_FD + 1, &selectFds, NULL, NULL, NULL);
count++;
}

printf("select() calls per second: %d\n", count);

pollFds.fd = HIGH_FD;
pollFds.events = POLLIN;
count = 0;
gotAlarm = 0;
alarm(1);
while (!gotAlarm) {
poll(&pollFds, 0, 0);
count++;
}

printf("poll() calls per second: %d\n", count);

return 0;
}


上述程序中,select()使用了/dev/zero, 它可以提供无数的零而导致系统立刻返回,可以通过改变HIGH_FD的值来观察select()性能是如何随着文件描述符的值增加而降低的。

当一个系统上HIGH_FD等于2的时候,程序可在1秒内处理的poll调用是select调用的四倍;HIGH_FD等于1000的时候,poll的效率就是select的40倍。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  select poll