Linux高级文件操作 -4

来源:互联网 发布:知乎嗜血法医 编辑:程序博客网 时间:2024/05/01 05:44

比较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 1000int 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倍。

0 0
原创粉丝点击