Linux下用过两种命令实现延时,分别是sleep
、usleep
;文中提到的nanosleep
是C函数,目前shell
解释器好像不支持、命令行中无法调用。
sleep
sleep n[unit]
:n
为暂停的时长,unit
为暂停的时间单位。
单位支持多种:秒、分、时、天
# 睡眠1秒
sleep 1s
# 睡眠1分
sleep 1m
# 睡眠1小时
sleep 1h
# 睡眠1天
sleep 1d
注意:
- 默认单位为秒,即
sleep 1
等价于sleep 1s
n
支持小数,如sleep 0.1
表示延迟100毫秒
usleep
与sleep
用法类似,但只支持一个单位:微秒。
如usleep 1000
表示1毫秒(单位换算参见附1)。
POSIX.1-2001已将
usleep
标注为废弃,POSIX.1-2008已删除usleep,应当使用nanosleep
替代usleep
在Solaris的多线程环境下编译器会自动把usleep()
连接成nanosleep()
。
nanosleep
精度是纳秒级。
nanosleep
是C函数,命令行不支持调用。
总结
- 一般情况下,延迟时间数量级是秒的时候,尽可能使用
sleep()
函数。- 如果延迟时间为几十毫秒(1ms = 1000us),或者更小,尽可能使用
usleep()
函数。这样才能最佳的利用CPU时间- 原则上
sleep()
和usleep()
都已废弃,函数调用时建议采用nanosleep()
。
三种命令的总结对比如下:
sleep |
usleep |
nanosleep |
|
---|---|---|---|
支持的单位 | 秒/分/时/天 | 微秒 | 纳秒 |
是否精确(见附3) | 不精确 | 不精确 具体偏差视系统调度间隔而定,一般为10ms |
不精确 |
线程安全 | 在一些平台下不是线程安全,如HP-UX以及Linux | 是 | |
信号安全 | 不能和alarm同时使用 | 不确定 | |
暂停效果与恢复 | 令目前的进程暂停,直到达到参数seconds 所指定的时间,或是被信号所中断 | ||
底层实现(见附2) | sleep()非系统调用,sleep()是在库函数中实现的,它是通过alarm()来设定报警时间,使用sigsuspend()将进程挂起在信号SIGALARM上 | 库函数中实现 | Linux中的系统调用,它是使用定时器来实现的,该调用使调用进程睡眠,并往定时器队列上加入一个timer_list型定时器,time_list结构里包括唤醒时间以及唤醒后执行的函数,通过nanosleep()加入的定时器的执行函数仅仅完成唤醒当前进程的功能。系统通过一定的机制定时检查这些队列(比如通过系统调用陷入核心后,从核心返回用户态前,要检查当前进程的时间片是否已经耗尽,如果是则调用schedule()函数重新调度,该函数中就会检查定时器队列,另外慢中断返回前也会做此检查),如果定时时间已超过,则执行定时器指定的函数唤醒调用进程。当然,由于系统时间片可能丢失,所以nanosleep()精度也不是很高 |
windows是否支持 | 否unistd.h 是UNIX系统标准头文件,用于系统调用,相当于win32中的windows.h,unistd.h 定义的函数只能用于UNIX环境中,而不能用于windows |
否 | 是 nalosleep 和其它时间日期操作函数,都是定义在 time.h 中的,所以Windows支持 |
其他说明 | unsigned int sleep(unsigned int seconds); 若进程暂停到参数seconds 所指定的时间,成功则返回0,若有信号中断则返回剩余秒数。 |
unsigned int usleep(unsigned int useconds); 除了时间单位为微秒以外,在使用上与sleep()差不多。还有就是实现也是不同的,sleep因为是用alarm实现的,所以时间单位为s ,而usleep的时间单位为us,那肯定不是由alarm实现的,所以说它们的实现不同,但都是linux用的,而window下不能用,因为都是sleep和usleep都是在unistd.h下定义的。return:若进程暂停到参数seconds 所指定的时间,成功则返回0,若有信号中断则返回剩余微秒数。 |
这个函数功能是暂停某个进程直到你规定的时间后恢复,参数req就是你要暂停的时间,其中req->tv_sec是以秒为单位,而tv_nsec以毫微秒为单位(10的-9次方秒)。由于调用nanosleep是是进程进入TASK_INTERRUPTIBLE,这种状态是会相应信号而进入TASK_RUNNING状态的,这就意味着有可能会没有等到你规定的时间就因为其它信号而唤醒,此时函数返回-1,切还剩余的时间会被记录在rem中。 return: 若进程暂停到参数req所指定的时间,成功则返回0,若有信号中断则返回-1,并且将剩余微秒数记录在rem中。 |
上面这些基本上说清楚命令的使用了,如果要了解底层原理,可以参考这篇文章:《Linux中延时/暂停函数(sleep/usleep/nanosleep/select)的比较、底层实现说明》、《Linux 高精確的時序(sleep, usleep,nanosleep)》
附1: 单位换算
中文名 | 英文名 | 英文缩写 | 换算 |
---|---|---|---|
秒 | second | s | 1000ms |
毫秒 | millisecond | ms | 1000μs |
微妙 | microsecond | μs | 1000ns |
纳秒 | nanosecond | ns | 1000ps |
皮秒 | picosecond | ps |
附2:命令系统实现代码摘录
sleep()-------以秒为单位
#include<unistd.h>
unsigned int sleep(unsigned int seconds);
return:若进程暂停到参数seconds 所指定的时间,成功则返回0,若有信号中断则返回剩余秒数。
在linux中,sleep是通过nanosleep实现的。在一些其他系统中(例如POSIX.1),它是通过alarm()来实现的。
usleep()----以微秒为单位
#include<unistd.h>
unsigned int usleep(unsigned int useconds);
return:若进程暂停到参数seconds 所指定的时间,成功则返回0,若有信号中断则返回剩余微秒数。
nanosleep( )---------以纳秒为单位
#include<time.h>
struct timespec
{
time_t tv_sec; /* 秒seconds */
long tv_nsec; /* 纳秒nanoseconds */
};
int nanosleep(const struct timespec *req, struct timespec *rem);
return: 若进程暂停到参数*req所指定的时间,成功则返回0,若有信号中断则返回-1,并且将剩余微秒数记录在*rem中。
req->tv_sec是以秒为单位,而tv_nsec以毫微秒为单位(10的-9次方秒)。
由于调用nanosleep是是进程进入TASK_INTERRUPTIBLE,这种状态是会相应信号而进入TASK_RUNNING状态的。
附3:精确度
与系统时钟关系(线程调度间隔):
我们假设时钟中断是10纳秒一次,如果tv_sec = 0, tv_nsec = 2,那么时钟中断一定是在10纳秒后来唤醒这个进程的,这里我们看到任务的重新调度最少是在10纳秒之上,因此此函数的精确程度与时钟频率有关系。
cpu的速度决定了时钟周期; 如, 一個 50 MHz 的CPU, 一個时钟周期的时间是 1/50000000 s(200 nsec)。
以上。感谢您的阅读。
转载:https://blog.csdn.net/zgdwxp/article/details/100767097