首先, 我会说不保证你在使用者模式 (user-mode) 中执行的行程

(process) 能够精确地控制时序因为 Linux 是个多工的作业环境. 你在执行中的行程 (process)

随时会因为各种原因被暂停大约 10 毫秒到数秒 (在系统负荷非常高的时候). 然而, 对於大多数使用 I/O 埠的应用而言,

这个延迟时间实际上算不了什麽. 要缩短延迟时间, 你得使用函式 nice 将你在执行中的行程 (process ) 设定成高优先权(请参考

nice(2)

使用说明文件) 或使用即时排程法 (real-time scheduling) (请看下面).

果你想获得比在一般使用者模式 (user-mode) 中执行的行程 (process) 还要精确的时序, 有一些方法可以让你在使用者模式

(user-mode) 中做到 `即时' 排程的支援. Linux 2.x 版本的核心中有软体方式的即时排程支援; 详细的说明请参考

sched_setscheduler(2)

使用说明文件. 有一个特殊的核心支援硬体的即时排程; 详细的资讯请参考网页

休息中 (Sleeping) :

sleep()

usleep()

现在, 让我们开始较简单的时序函式呼叫. 想要延迟数秒的时间, 最佳的方法大概 是使用函式

sleep()

. 想要延迟至少数十毫秒的时间 (10 ms 似乎已是最短的 延迟时间了), 函式

usleep()

应该可以使用. 这些函式是让出 CPU 的使用权 给其他想要执行的行程 (processes) (``自己休息去了''), 所以没有浪费掉 CPU 的时间. 细节请参考

sleep(3)

usleep(3)

的说明文件.

果让出 CPU 的使用权因而使得时间延迟了大约 50 毫秒 (这取决於处理器与机器的速度, 以及系统的负荷), 就浪费掉 CPU 太多的时间,

因为 Linux 的排程器 (scheduler) (单就 x86 架构而言) 在将控制权发还给你的行程 (process)

之前通常至少要花费 10-30 毫秒的时间. 因此, 短时间的延迟, 使用函式

usleep(3)

所得到的延迟结果通常会大於你在参数所指定的值, 大约至少有 10 ms.

nanosleep()

在 Linux 2.0.x 一系列的核心发行版本中, 有一个新的系统呼叫 (system call),

nanosleep()

(请参考

nanosleep(2)

的说明文件), 他让你能够 休息或延迟一个短的时间 (数微秒或更多).

如果延迟的时间 <= 2 ms, 若(且唯若)你执行中的行程 (process) 设定了软体的即时 排程 (就是使用函式 tt/sched_setscheduler()/), 呼叫函式

nanosleep()

时 不是使用一个忙碌回圈来延迟时间; 就是会像函式

usleep()

一样让出 CPU 的使用权休息去了.

这个忙碌回圈使用函式

udelay()

(一个驱动程式常会用到的核心内部的函式) 来达成, 并且使用 BogoMips 值 (BogoMips 可以准确量测这类忙碌回圈的速度) 来计算回圈延迟的时间长度. 其如何动作的细节请参考

/usr/include/asm/delay.h

).

使用 I/O 埠来延迟时间

一个延迟数微秒的方法是使用 I/O 埠. 就是从埠位址 0x80 输入或输出任何 byte 的资料 (请参考前面) 等待的时间应该几乎只要 1

微秒这要看你的处理器的型别与速度. 如果要延迟数微秒的时间你可以将这个动作多做几次. 在任何标准的机器上输出资料到该

埠位址应该不会有不良的後果□对 (而且有些核心的设备驱动程式也在使用他).

{in|out}[bw]_p()

等函式就是使用这个方法来产生时间延迟的 (请参考档案

asm/io.h

).

实际上, 一个使用到埠位址□围为 0-0x3ff 的 I/O 埠指令几乎只要 1 微秒的时间, 所以如果你要如此做, 例如, 直接使用并列埠, 只要加上几个

inb()

函式从该 埠位址□围读入 byte 的资料即可.

使用组合语言来延迟时间

果你知道执行程式所在机器的处理器型别与时钟速度, 你可以执行某些组合语言指令以便获得较短的延迟时间 (但是记住, 你在执行中的行程

(process) 随时会被暂停, 所以有时延迟的时间会比实际长). 如下面的表格所示, 内部处理器的速度决定了所要使用的时钟周期数; 如,

一个 50 MHz 的处理器 (486DX-50 或 486DX2-50), 一个时钟周期要花费 1/50000000 秒 (=200

奈秒). 指令 i386 时钟周期数 i486 时钟周期数

nop 3 1

xchg %ax,%ax 3 3

or %ax,%ax 2 1

mov %ax,%ax 2 1

add %ax,0 2 1

(对不起, 我不知道 Pentiums 的资料, 或许与 i486 接近吧. 我无法在 i386 的资料上找到只花费一个时钟周期的指令. 如果能够就请使用花费一个时钟周期的指令, 要不然就使用管线技术的新式处理器也是可以缩短时间的.)

上面的表格中指令

nop

xchg

应该不会有不良的後果. 指令最後可能会 改变旗号暂存器的内容, 但是这没关系因为 gcc 会处理. 指令

nop

是个好的选择.

想要在你的程式中使用到这些指令, 你得使用

asm("instruction")

. 指令的语法就如同上面表格的用法; 如果你想要在单一的

asm()

叙述中使用多个指令, 可以使用分号将他们隔开. 例如,

asm("nop ; nop ; nop ; nop")

会执行四个

nop

指令, 在 i486 或 Pentium 处理器中会延迟四个时钟周期 (或是 i386 会延迟 12 个时钟周期).

gcc 会将

asm()

翻译成单行组合语言程式码, 所以不会有呼叫函式的负荷.

在 Intel x86 架构中不可能有比一个时钟周期还短的时间延迟.

在 Pentiums 处理器上使用函式

rdtsc

对於 Pentiums 处理器而言, 你可以使用下面的 C 语言程式码来取得自从上次重新开机 到现在经过了多少个时钟周期:

extern __inline__ unsigned long long int rdtsc()

{

unsigned long long int x;

__asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));

return x;

}

你可以询问参考此值以便延迟你想要的时钟周期数.

想要时间精确到一秒钟, 使用函式

time()

或许是最简单的方法. 想要时间更精确, 函式

gettimeofday()

大约可以精确到微秒 (但是如前所述会受到 CPU 排程的影响). 至於 Pentiums 处理器, 使用上面的程式码片断就可以精确到一个时钟周期.

如果你要你执行中的行程 (process) 在一段时间到了之後能够被通知 (get a signal), 你得使用函式

setitimer()

alarm()

. 细节请参考函式的使用说明文件.

应用程序:

#include

usleep(n) //n微秒

Sleep(n)//n毫秒

sleep(n)//n秒

驱动程序:

#include

mdelay(n) //milliseconds 其实现

#ifdef notdef

#define mdelay(n) (\

{unsigned long msec=(n); while (msec--) udelay(1000);})

#else

#define mdelay(n) (\

(__builtin_constant_p(n) && (n)<=MAX_UDELAY_MS) ? udelay((n)*1000) : \

({unsigned long msec=(n); while (msec--) udelay(1000);}))

#endif

调用asm/delay.h的udelay,udelay应该是纳秒级的延时

Dos:

sleep(1); //停留1秒

delay(100); //停留100毫秒

Windows:

Sleep(100); //停留100毫秒

Linux:

sleep(1); //停留1秒

usleep(1000); //停留1毫秒

每一个平台不太一样,最好自己定义一套跨平台的宏进行控制

秒还是微秒?关于延时函数sleep()

因为要写一段代码,需要用到sleep()函数,在我印象中,sleep(10)好像是休眠10微秒,结果却是休眠了10秒(在Linux下)。觉得很奇怪,因为头儿也记得好像是微秒为单位的。所以就查了一下。

原来linux下的sleep函数原型为:

unsigned int sleep(unsigned int seconds);

而MFC中的Sleep函数原型为:

void Sleep(DWORD dwMilliseconds);

就是说,Linux下(使用的gcc的库),sleep()函数是以秒为单位的,sleep(1);就是休眠1秒。而MFC下的sleep()函数是以微

秒为单位的,sleep(1000);才是休眠1秒。原来如此啊。而如果在Linux下也用微妙为单位休眠,可以使用线程休眠函数:void

usleep(unsigned long usec);当然,使用的时候别忘记#include 哦。

另外值得一提的是,linux下还有个delay()函数,原型为extern void delay(unsigned int msec);它可以延时msec*4毫秒,也就是如果想延时一秒钟的话,可以这么用 delay(250);

小小一个延时函数原来还有这么多学问,任何一点代码都不可小看啊。

linux usleep 函数,Linux 高精確的時序(sleep, usleep,nanosleep)相关推荐

  1. linux usleep函数,linux下,测试usleep函数对CPU占用率的影响

    一.本机环境 CPU信息 Intel(R) Core(TM) i3 CPU  M 350  @ 2.27GHz Intel(R) Core(TM) i3 CPU  M 350  @ 2.27GHz I ...

  2. linux线程调度函数,Linux调度策略及线程优先级设置

    Linux内核的三种调度策略: 1,SCHED_OTHER 分时调度策略, 2,SCHED_FIFO实时调度策略,先到先服务.一旦占用cpu则一直运行.一直运行直到有更高优先级任务到达或自己放弃 3, ...

  3. linux backtrack函数,Linux调用backtrack函数打印程序崩溃时的调用堆栈

    可以给自己的程序都加上这个东西,便于快速的找到错误吧,看到别人都是这么用的 #include #include #include #include //signal 函数用法参考http://www. ...

  4. linux suspend函数,linux pm-suspend过程彻底研究

    linux pm-suspend过程彻底研究 上一篇 / 下一篇  2008-04-10 21:18:35 / 个人分类:Linux 1.pm-suspend-->symbol link to ...

  5. linux fork 函数,Linux的fork()系统调用

    Linux的fork()系统调用,就是以父进程为模版创建子进程,是Linux系统的进程管理机制的核心API之一,另一个是调度器函数schedule(),它的用户态API就是之前说自旋锁时提到的sche ...

  6. linux receive函数,Linux网络 - 数据包的接收过程

    的方式写入到指定的内存地址,该地址由网卡驱动分配并初始化.注: 老的网卡可能不支持DMA,不过新的网卡一般都支持. 3: 网卡通过硬件中断(IRQ)通知CPU,告诉它有数据来了 4: CPU根据中断表 ...

  7. linux sysconf函数,linux c sysconf函数 得到系统配置

    函数原型: NAME sysconf - Get configuration information at runtime SYNOPSIS #include long sysconf(int nam ...

  8. linux blind函数,Linux网络编程入门

    上一节创建socket时,仅指定了协议类型以及服务类型,但是没有指定具体的socket地址. bind函数含义如词义,给上述创建的套接字socket绑定一个socket地址. 比喻如下:我们创建了so ...

  9. make找不到linux内核函数,linux内核make menuconfig出错

    今天实验刚从服务器上迁移过来的维护的linux 9260的内核,使用make menuconfig时出错,报错为: yongtao@yongtao-desktop:~/public/linux_rel ...

最新文章

  1. AIX如何查看文件系统分布在哪个物理磁盘上
  2. php 读写文件 file_put_contents() 与 file_get_contents() 函数用法
  3. Android消息机制——时钟显示和异步处理工具类(AsyncTask)
  4. linux跳出循环的三种方式,shell study-13day--跳出循环(break、continue)
  5. 列表解析和生成器表达式
  6. OpenCV各向异性图像分割anisotropic image segmentation的实例(附完整代码)
  7. JAVA ++ 运算符题目
  8. Android之给ImageView添加点击效果
  9. 【转】DCMTK各模块说明!!!!!!!
  10. 吕述望 计算机网络专家,特稿: 中科院吕述望教授:互联网名不符实
  11. LMbench - Tools for Performance Analysis | 内核基准测试
  12. cropbox.js 头像裁剪插件
  13. [转]cookie、sesstion、localstorage、sesstionstorage的使用和区别
  14. java使用io上传文件_文件传输基础——Java IO流
  15. 单片机数码管万年历c语言,基于51单片机和数码管的万年历程序
  16. 基于FPGA的SDRAM控制器设计(一)
  17. mac 环境变量 配置
  18. word技巧-分节符和连续页码,页眉页脚加线
  19. 用html制作一个网站的步骤,新手怎么做网页 新手如何制作一个网页
  20. wind10 使用Hyper-V安装centos7遇到的问题及解决方案

热门文章

  1. python画条形统计图_python基础绘图-统计图
  2. YugaByte评论:行星级Cassandra和Redis
  3. 关闭电脑网页百度右侧百度热搜
  4. 携手中建·城发,30天极速交付中建星光城市会客厅
  5. 让开发部署提速 8 倍的 IDE 插件
  6. 终结代购跨境直购新选择
  7. android toast 自定义时间,Android Toast自定义显示时间
  8. 宠物短视频的三种类型分享,选择最适合自己的方向,才能事半功倍
  9. background与background-color 你“不知道”的区别
  10. 微信小程序全局配置文件app.json中window:backgroundColor“不生效”