select( 1)

非阻塞 I/O 经常使用 poll(System V)、select(BSD Unix)、 epoll(linux2.5.45开始)系统调用。
select()的调用形式为:
    #include <sys/select.h>
    #include <sys/time.h>
    int select(int maxfd,                   /*
要被检测的比特数,待检测的最大文件描述符大1*/
                 fd_set *readfds,             /*
被读监控的文件描述符集*/
                 fd_set *writefds,            /*
被读监控的文件描述符集*/
                 fd_set *exceptfds,         /*
被例外条件监控的文件描述符集*/
                 const struct timeval *timeout);/*
定时器的作用*/

maxfd  是最大描述符加1.

3个描述符集若不感兴趣,就可以设置为NULL.

   参数timeout到了指定的时间,无论是否有设备准备好,都返回调用。timeval的结构定义如下:
    struct timeval{
        long tv_sec; //秒
        long tv_usec; //微秒
    }

    timeout取不同的值,该调用就表现不同的性质:
    timeout为0,调用立即返回;称为轮询。
    timeout为NULL,select()调用就阻塞,直到知道有文件描述符就绪;永远等下去。
    timeout为正整数,就是一般的定时器

select调用返回时,除了那些已经就绪的描述符外,select将清除readfds、writefds和exceptfds中的所有没有就绪的描述符。再次调用时要重新置描述符。

select的返回值有如下情况:
    正常情况下返回就绪的文件描述符个数;
    经过了timeout时长后仍无设备准备好,返回值为0;
    如果select被某个信号中断,它将返回-1并设置errno为EINTR。
    如果出错,返回-1并设置相应的errno。

 

系统提供了4个宏对描述符集进行操作:
    #include <sys/select.h>
    #include <sys/time.h>
    void FD_SET(int fd, fd_set *fdset);
    void FD_CLR(int fd, fd_set *fdset);
    void FD_ISSET(int fd, fd_set *fdset);
    void FD_ZERO(fd_set *fdset);

    FD_SET    设置文件描述符集fdset中对应于文件描述符fd的位(设置为1)
    FD_CLR    清除文件描述符集fdset中对应于文件描述符fd的位(设置为 0)
    FD_ZERO   清除文件描述符集fdset中的所有位(既把所有位都设置为0)。
    使用这3个宏在调用select前设置描述符屏蔽位

    在调用select后使用
    FD_ISSET来检测文件描述符集fdset中对应于文件描述符fd的位是否被设置。

fd_set
---------------------------------------------------------
typedef __kernel_fd_set     fd_set;

typedef struct {
    unsigned long fds_bits [__FDSET_LONGS];
} __kernel_fd_set;

#define __FDSET_LONGS   (__FD_SETSIZE/__NFDBITS)
#define __FD_SETSIZE    1024
#define __NFDBITS       (8 * sizeof(unsigned long))


    过去,描述符集被作为一个整数位屏蔽码得到实现,但是这种实现对于多于32个的文件描述符将无法工作。描述符集现在通常用整数数组中的位域表示,数组元素的每一位对应一个文件描述符。例如,一个整数占32位,那么整数数组的第一个元素代表文件描述符0到31,数组的第二个元素代表文件描述符32到63,以此类推。宏FD_SET设置整数数组中对应于fd文件描述符的位为1,宏FD_CLR设置整数数组中对应于fd文件描述符的位为0,宏FD_ZERO设置整数数组中的所有位都为0。

  假设执行如下程序后:
    #include <sys/select.h>
    #include <sys/time.h>
    fd_set readset;
    FD_ZERO(&readset);
    FD_SET(5, &readset);
    FD_SET(33, &readset);

    再执行如下程序后:
    FD_CLR(5, &readset);

    通常,操作系统通过宏_FD_SETSIZE来声明在一个进程中select所能操作的文件描述符的最大数目。例如:
    #define _FD_SETSIZE 1024
    既定义_FD_SETSIZE为1024,一个整数占4个字节,既32位,那么就是用包含32个元素的整数数组来表示文件描述符集。我们可以在头文件中修改这个值来改变select使用的文件描述符集的大小,但是必须重新编译内核才能使修改后的值有效。当前版本的unix操作系统没有限制 _FD_SETSIZE的最大值,通常只受内存以及系统管理上的限制。

select的中间三个指向描述符集的参数若全部为空指针,则select提供了较sleep(等待整数秒)更为精确的计时器。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值