转自:https://www.cnblogs.com/longbiao831/p/4556246.html 

Select只能做延时,可以做回调吗?

本文讲述如何使用select实现超级时钟。使用select函数,我们能实现微妙级别精度的定时器。同时,select函数也是我们在编写非阻塞程序时经常用到的一个函数
 
 

在编写程序时,我们经常会用到定时器。首先看看select函数原型如下:
代码如下:

int select(int nfds, fd_set *readfds, fd_set *writefds,
                  fd_set *exceptfds, struct timeval *timeout);

参数说明:
slect的第一个参数nfds为fdset集合中最大描述符值加1,fdset是一个位数组,其大小限制为__FD_SETSIZE(1024),位数组的每一位代表其对应的描述符是否需要被检查。
select的第二三四个参数表示需要关注读、写、错误事件的文件描述符位数组,这些参数既是输入参数也是输出参数,可能会被内核修改用于标示哪些描述符上发生了关注的事件。所以每次调用select前都需重新初始化fdset。
timeout参数为超时时间,该结构会被内核修改,其值为超时剩余的时间。
利用select实现定时器,需要利用其timeout参数,注意到:
 1)select函数使用了一个结构体timeval作为其参数。
 2)select函数会更新timeval的值,timeval保持的值为剩余时间。
如果我们指定了参数timeval的值,而将其他参数都置为0或者NULL,那么在时间耗尽后,select函数便返回,基于这一点,我们可以利用select实现精确定时。
timeval的结构如下:
代码如下:

struct timeval{
long tv_sec;/*secons*
long tv_usec;/*microseconds*/
}

我们可以看出其精确到microseconds也即微妙。
一、秒级定时器
代码如下:

void seconds_sleep(unsigned seconds){
    struct timeval tv;
    tv.tv_sec=seconds;
    tv.tv_usec=0;
    int err;
    do{
       err=select(0,NULL,NULL,NULL,&tv);
    }while(err<0 && errno==EINTR);
}

二、毫秒级别定时器
代码如下:

void milliseconds_sleep(unsigned long mSec){
    struct timeval tv;
    tv.tv_sec=mSec/1000;
    tv.tv_usec=(mSec%1000)*1000;
    int err;
    do{
       err=select(0,NULL,NULL,NULL,&tv);
    }while(err<0 && errno==EINTR);
}

三、微妙级别定时器
代码如下:

void microseconds_sleep(unsigned long uSec){
    struct timeval tv;
    tv.tv_sec=uSec/1000000;
    tv.tv_usec=uSec%1000000;
    int err;
    do{
        err=select(0,NULL,NULL,NULL,&tv);
    }while(err<0 && errno==EINTR);
}

现在我们来编写几行代码看看定时效果吧。
代码如下:

#include <stdio.h>
#include <sys/time.h>
#include <errno.h>
int main()
{
    int i;
    for(i=0;i<5;++i){
    printf("%d\n",i);
    //seconds_sleep(1);
    //milliseconds_sleep(1500);
    microseconds_sleep(1900000);
    }

}

注:timeval结构体中虽然指定了一个微妙级别的分辨率,但内核支持的分别率往往没有这么高,很多unix内核将超时值向上舍入成10ms的倍数。此外,加上内核调度延时现象,即定时器时间到后,内核还需要花一定时间调度相应进程的运行。因此,定时器的精度,最终还是由内核支持的分别率决定。

[Timer]应用层实现sleep的更多相关文章

  1. 应用层timer_如何序列化timer

    应用层使用timer可以启动多个timer(每个timer管理一个目标时间),也可启用一个timer来管理多个目标时间. 多个timer时每个timer占用一部分空间,且存在多个timer同时到期的先 ...

  2. 应用层timer_libc_posix timer

    应用层除了通过setitimer/getitimer设置获取timer外,还可通过timer_create()等一系列函数实现应用层timer功能. 应用流程 The timers created b ...

  3. Linux应用层的定时器Timer使用详解【转】

    转自:http://blog.csdn.net/wwwtovvv/article/details/8601528 版权声明:本文为博主原创文章,未经博主允许不得转载. linux下定时器的使用 -- ...

  4. C#中自定义高精度Timer定时器的实例教程

    Timer 用于以用户定义的事件间隔触发事件.Windows 计时器是为单线程环境设计的,其中,UI 线程用于执行处理.它要求用户代码有一个可用的 UI 消息泵,而且总是在同一个线程中操作,或者将调用 ...

  5. Linux 应用层的时间编程【转】

    转自:https://blog.csdn.net/chinalj2009/article/details/21223681 浅析 Linux 中的时间编程和实现原理,第 1 部分: Linux 应用层 ...

  6. TCP系列32—窗口管理&流控—6、TCP zero windows和persist timer

    一.简介 我们之前介绍过,TCP报文中的window size表示发出这个报文的一端准备多少bytes的数据,当TCP的一端一直接收数据,但是应用层没有及时读取的话,数据一直在TCP模块中缓存,最终受 ...

  7. TimesTen 应用层数据库缓存学习:4. 仅仅读缓存

    在运行本文样例前.首先先运行TimesTen 应用层数据库缓存学习:2. 环境准备中的操作. Read-only Cache Group的概念 仅仅读缓存组例如以下图: 仅仅读缓存组(Read-Onl ...

  8. 浅析 Linux 中的时间编程和实现原理一—— Linux 应用层的时间编程【转】

    本文转载自:http://www.cnblogs.com/qingchen1984/p/7007631.html 本篇文章主要介绍了"浅析 Linux 中的时间编程和实现原理一—— Linu ...

  9. ABP(现代ASP.NET样板开发框架)系列之15、ABP应用层——应用服务(Application services)

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之15.ABP应用层——应用服务(Application services) ABP是“ASP.NET Boiler ...

随机推荐

  1. 【转】我为什么离开 Cornell

    我为什么离开 Cornell 很多人都知道,我曾经在 Cornell 博士就读,两年之后转学到了 Indiana 大学.几乎所有人,包括 Indiana 大学的人都感觉奇怪,为什么会有人从 Corne ...

  2. SharePoint 关于拓扑错误的解决方案

    Issue Topology报错信息:SharePoint Web Services Round Robin Service Load Balancer Event: EndpointFailure. ...

  3. android开发之interpolator的使用

    android:interpolator Interpolator 被用来修饰动画效果,定义动画的变化率,可以使存在的动画效果accelerated(加速),decelerated(减速),repea ...

  4. android中碰撞屏幕边界反弹问题

    其实碰撞问题只是涉及到一点小算法而已,但在实际应用,尤其游戏中有可能会遇到,下面给出一个小示例,代码如下: MainActivity: package com.lovo; import android ...

  5. 并发测试 JavaDemo

    https://github.com/oldratlee/fucking-java-concurrency /** * @author Jerry Lee */ public class Testee ...

  6. jmeter压测前清理内存

    jmeter 压测时设置了内存为sed -i 's/HEAP="-Xms512m -Xmx512m"/HEAP="-Xms36096m -Xmx360096m" ...

  7. 类里的通用成员函数应声明为static

    类C的成员函数f,如果f的实现实现不依赖于C的任何成员变量,则f为通用函数. 对于通用函数f,可以将其从类C中分离出来做成一个全局函数,也可以仍然让它属于类C,但加上static. 两种处理方法实际都 ...

  8. 使用git上传项目到码云

    一.git安装 1.首先在官方网站下载git工具,或者根据以下链接进行下载:http://download.csdn.net/detail/qq_27501889/9788879(此链接版本为git- ...

  9. PureFtpd 连接数据库错误

    用Ubuntu一段时间了,作为服务器真是好用,还轻快的很. 作为服务器怎么能没有ftp呢,这里用了pureftpd,没有用vsftpd是因为听大牛说听麻烦,没用过没发言权,不过pureftpd真的挺好 ...

  10. IOS 实现录音PCM转MP3格式(边录音边转码)

    最近做的一个项目,项目中有个录音功能,采用的录音方法是IOS下的AVAudioRecorder.录音效果不错,但是录制的原生.pcm文件太大,每分钟大约10M左右. 找了下相关的音频压缩方法,用spe ...