select函数

axel中的axel_do函数中使用了select()函数,碰巧我正在看UNP的第六章讲的也是select函数,所以简单总结一下。

 

这里先列出axel_do函数中使用的select。

    FD_ZERO( fds );

    hifd = 0;

    for( i = 0; i < axel->conf->num_connections; i ++ )

    {

        if( axel->conn[i].enabled )

            FD_SET( axel->conn[i].fd, fds );

        hifd = max( hifd, axel->conn[i].fd );

    }

    if( hifd == 0 )

    {

        /* No connections yet. Wait...                */

        usleep( 100000 );

        goto conn_check;

    }

    else

    {

        timeval->tv_sec = 0;

        timeval->tv_usec = 100000;

        /* A select() error probably means it was interrupted

           by a signal, or that something else's very wrong...    */

        if( select( hifd + 1, fds, NULL, NULL, timeval ) == -1 )

        {

            axel->ready = -1;

            return;

        }

    }

    

    /* Handle connections which need attention            */

    for( i = 0; i < axel->conf->num_connections; i ++ )

    if( axel->conn[i].enabled ) {

    if( FD_ISSET( axel->conn[i].fd, fds ) )

    {

        axel->conn[i].last_transfer = gettime();

        size = read( axel->conn[i].fd, buffer, axel->conf->buffer_size );

        if( size == -1 )

        {

            if( axel->conf->verbose )

            {

                axel_message( axel, _("Error on connection %i! "

                    "Connection closed"), i );

            }

            axel->conn[i].enabled = 0;

            conn_disconnect( &axel->conn[i] );

            continue;

        }

为啥要使用select()

那么为啥需要使用select()函数呢?换句话说select函数的作用是啥?引用一句UNP上的话:

“select函数允许进程指示内核等待多个事件中的任何一个发生,并仅在有一个或多个事件发生或者经历一段指定的事件后才唤醒它。”

换句话说,有一个容器里面装了若干个事件,这些事件发生的顺序不清楚,但是发生之后要进行相应的处理。select函数的作用就是保持阻塞直到这些事件中的某一个发生,或者没事件发生的但过了一段指定的时间(超时时间)。

那么axel_do函数中使用的select的用意是啥呢?

其实从上面的代码中很容易看出来,这段代码的作用是要读有数据过来的socket。而axel在下载的时候是多连接的,我们不知道什么时候哪一个socket准备好了,于是不可能阻塞在一个socket上,取而代之的是阻塞在select函数上,直到有socket准备好,这样显然增加了效率。

 

先给出select()的原型:

int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout);

·fd_set实际上是一个long的数组,fd_set数组中每一位对应一个描述符,就像是位(bit)一样,当某一位被置位,说明这一位对应的描述符在当前的描述符集合里。

timeout就是超时时间。

readfds,writefds,errorfds分别代表的是测试可读、可写、异常的描述符集合。

 

和select函数相关的四个宏:

FD_ZERO(fd_set *fdset)
FD_SET(int fd, fd_set *fdset)

FD_CLR(int fd, fd_set *fdset)
FD_ISSET(int fd, fdset *fdset)

清除fdset集合
将fd在fdset集合中置位,也就是将fd加入fdset
在fdset集合中清楚fd
测试fd是否在fdset中置位

你可能感兴趣的:(select)