linux c中select使用技巧——计时器(转)

通过本文你会了解到: 
1. select()原型及参数说明 
2. select()应用情景 
3. select()注意事项 
4. select()作定时器

原型

1 int select(int nfds, fd_set *readfds, fd_set *writefds,
2                   fd_set *exceptfds, struct timeval *utimeout);

 

参数说明 
readfdswritefdsexceptfds为所要监听的三个描述符集: 
——readfds 监听文件描述符是否可读,不监听可以传入 NULL 
——writefds 监听文件描述符是否可写 ,不监听可以传入 NULL 
——exceptfds 监听文件描述符是否有异常,不监听可以传入 NULL 
nfds 是 select() 监听的三个描述符集中描述符的最大值+1 
timeout 设置超时时间 
更详细信息请参考译文linux-select()

应用情景 
select() 函数的重点在于它可以同时监控多个描述符(一般最大为1024),并且在描述符集中没有可操作的描述符时会进入睡眠状态。 实际应用中,若需要同时处理多个描述符的读写时,如果只是创建了一系列的read()write()就会导致在有些描述符没有准备好读写时而被阻塞,这样当然不是我们期望的,因此这时就需要应用select()

注意事项 
这段是select()使用必须要了解和掌握的知识点,建议认真阅读,同时可以结合后续的一些实例做分析,相信你一定能掌握select()使用方法。

  1. nfds必须被正确设置,一般取描述符集中描述符的最大值并加1。
  2. 在非必须的情况下,尽量使用不超时的select(),即将utimeout参数设置为NULL

    1 /*参数 timeout 置为 NULL*/
    2 select(nfds, &readfds, &writefds, &exceptfds, NULL);

     

  3. timeout的值必须在每次select()之前重新赋值,因为操作系统会修改此值。

    1 while(1) {
    2    timeout.tv_sec = 1;
    3    timeout.tv_usec = 0;
    4    select(nfds, &readfds, &writefds, &exceptfds, &timeout);
    5 }

     

  4. 由于select()会修改字符集,因此如果select()调用是在一个循环中,则描述符集必须被重新赋值。

    1 /*以read操作为例*/
    2 while(1) {
    3    FD_ZERO(&readfds);
    4    FD_SET(fd, &readfds);
    5    select(nfds, &readfds, NULL, NULL, NULL);
    6 }

     

  5. 函数read()write()recv()send()以及select()可能会返回-1并且errno置位为EINTR,或这errno被赋值为EAGAIN(EWOULDBLOCK),这种情况需要被正确处理。如果程序中不接收任何信号,则不会得到EINTR。如果程序设为阻塞I/O,则不会收到EAGAIN。

    1 /*一般只需对EINTR进行处理就可以了,例子如下*/
    2 while(1) {
    3    ret = select(nfds, &readfds, NULL, NULL, NULL);
    4    if(ret == -1 && errno == EINTR)
    5        continue;
    6 }

     

  6. read()write()recv()send()返回0时建议关闭描述符并在字符集中移除此描述符(不关闭描述符并移除的话可能会导致未知错误,还是对此情况处理的好)。

定时器 
在没有usleep函数的系统中,可以应用select来实现,下例中实现了0.2秒的延时:

1 struct timeval tv;
2 tv.tv_sec = 0;
3 tv.tv_usec = 200000; /* 0.2 秒*/
4 select(0, NULL, NULL, NULL, &tv);

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值