linux使用select实现精确定时器详解_linux shell

在编写程序时,我们经常会用到定时器。首先看看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的倍数。此外,加上内核调度延时现象,即定时器时间到后,内核还需要花一定时间调度相应进程的运行。因此,定时器的精度,最终还是由内核支持的分别率决定。
分类: Linux

时间: 2025-01-07 01:26:36

linux使用select实现精确定时器详解_linux shell的相关文章

一天一个shell命令 linux文件操作系列-ln命令详解_linux shell

里提示一下:ubuntu的翻译很多都是字面直译,存在很多问题,所以建议大家参照我这里的解释.当然本来也是有些赶文的嫌疑,望指正. 经常在linux上操作,有在不同的目录下切换某几个固定的命令,或者修改几个固定的文件,这时候,如果能在一个目录下就操作他们,会是一件多么轻松的事情.我们来看看链接命令ln 全称 ln 全称是link 顾名思义,这是一个建立一个链接.怎么去理解呢?它的功能类似于Mac OS的别名或者Windows的快捷方式, 删除不会影响文件本身. 说明:(直接看看斜体,就行了) 链接

一天一个shell命令 linux好管家-磁盘-du命令详解_linux shell

du命令 磁盘管理 du命令也是查看使用空间的,但是与df命令不同的是Linux du命令是对文件和目录磁盘使用的空间的查看,还是和df命令有一些区别的. 语法 du [选项][文件] 选项 -a或-all 显示目录中个别文件的大小. -b或-bytes 显示目录或文件大小时,以byte为单位. -c或--total 除了显示个别目录或文件的大小外,同时也显示所有目录或文件的总和. -k或--kilobytes 以KB(1024bytes)为单位输出. -m或--megabytes 以MB为单位

一天一个shell命令 linux好管家-进程-ps命令详解_linux shell

小知识(以ps为例): 查看命令路径  which ps 命令帮助 ps --help 命令完全手册: man ps 说明 ps全称是:Process Status (进程状态),他就是提供进程信息的. ps命令用于报告当前系统的进程状态.可以搭配kill指令随时中断.删除不必要的程序.ps命令是最基本同时也是非常强大的进程查看命令,使用该命令可以确定有哪些进程正在运行和运行的状态.进程是否结束.进程有没有僵死.哪些进程占用了过多的资源等等,总之大部分信息都是可以通过执行该命令得到的. 附知识说

一天一个shell命令 linux好管家--磁盘--df命令详解_linux shell

df命令 磁盘管理 df命令用于显示磁盘分区上的可使用的磁盘空间.默认显示单位为KB.可以利用该命令来获取硬盘被占用了多少空间,目前还剩下多少空间等信息. 语法 df(选项)(参数) 选项 -a或--all:包含全部的文件系统: --block-size=<区块大小>:以指定的区块大小来显示区块数目: -h或--human-readable:以可读性较高的方式来显示信息: -H或--si:与-h参数相同,但在计算时是以1000 Bytes为换算单位而非1024 Bytes: -i或--inod

一天一个shell命令 linux文本操作系列-tree命令详解_linux shell

tree命令是以图形化的树结构打印文件和目录的主角.通常linux发行版本中并没有包括这个命令.你需要用包管理器自行安装. 实例: 1. tree 打印当前目录下所有文件 2. tree –p ${dir} 打印dir目录下所有文件,以及他们的权限 3. tree –h ${dir} 打印dir目录下所有文件,以及适读的大小 4. tree path –P "*.sh" 打印所有.sh结尾的文件 5. tree path –H http://localhost –o out.html

一天一个shell命令 linux文本操作系列-diff命令详解_linux shell

这又是一个文件比较命令,熟练掌握会节省你很多工作.还记得comm命令吗?diff比他更加复杂,好用,不仅能比较文件,还能比较目录. 当一个文件有多个版本时候,或者更多复杂的文件,目录比较时,你会期望有一个比comm更有用的命令,diff正是为此而生. 全称:different file 实例: 文件1: v1.txt 复制代码 代码如下: hello   world v1_echo   v1_diff   v1_comm  shell is easy! 文件2: v2.txt 复制代码 代码如下

linux awk时间计算脚本及awk命令详解_linux shell

在linux如果计划时间是个麻烦事, 用awk脚本如下 BEGIN {FS=":";OFS=":"} {total_seconds=total_seconds+$3} total_seconds>=60 {total_seconds=total_sconds-60 $2=$2+1 } {total_minutes=total_minutes+$2 $2=$2+1 } {total_minutes=total_minutes+$2} total_minutes&

一天一个shell命令 linux文本操作系列-tac,rev命令详解_linux shell

说明: tac和rev没有必然联系,唯一相同的是,他们是"反派".tac其实是cat的反写,cat正常输出,那tac就倒着输出,不过从行的最后一行输出,那rev呢?rev是每行的最后一个字母到第一个字母倒序输出. 简单实例 tac命令 文件过滤分割与合并 tac命令用于将文件已行为单位的反序输出,即第一行最后显示,最后一行先显示. 语法 tac(选项)(参数) 选项 -a或--append:将内容追加到文件的末尾: -i或--ignore-interrupts:忽略中断信号. 参数 文

Shell编程中while与for的区别及用法详解_linux shell

在shell编程中经常用到循环,常用的循环有for和while循环两种.while循环默认以行读取文件,而for循环以空格读取文件切分文件,本篇就结合现网的一些使用示例说说二者的用法和区别. 一.常用语法 1.for循环 for循环常用的语法结构有如下几种: for 变量 in seq字符串 for 变量 in `command` " " for 变量 in "$@"或"$*" for((赋值:条件:运算语句)) 2.while循环 while循