C语⾔的sleep、usleep、nanosleep等休眠函数的了解与⽤法
C语⾔的sleep、usleep、nanosleep等休眠函数的了解与⽤法
昨天晚上,⽆聊中捣⿎「死循环」⼩代码的时候,想⽤ 休眠 函数来慢慢显⽰输出结果,免得输出结果闪得太快,看都看不清。
但是,使⽤ sleep 函数的话,最短的休眠时间段是⼀秒钟,要想看到⽐较⼤的输出结果的话,要等好久,于是就查了⼀下有没有休眠时间段更⼩的函数。很容易地就到了两个,⼀个是 usleep ,⼀个是 nanosleep 函数。
因为是第⼀次使⽤,尤其是 nanosleep 函数的第⼀个参数是⼀个没见过的结构体数据类型,所以花了⼀点点时间去学习和探索背后的细节,当然了,对于俺⽬前的⽔平⽽⾔,也只是了解了函数本⾝层⾯的浅显的细节⽽已。
捣⿎下来,觉得内容也不少,⽽且还是挺有⽤的,就整理了⼀下,组合成⽂章,发布在这⾥,也⽅便⾃⼰以后的回顾学习。
引⼦
⼀个⽆聊的死循环⼩代码:
#include<stdio.h>
int main(int argc,char const*argv[])
{
for(char c =0; c <128; c++){
printf("cool\n");
}
return0;
}
以及 运⾏过程 展⽰版:
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<unistd.h>
int main(int argc,char const*argv[])
{
struct timespec n_sleep;
n_sleep.tv_sec =0;//secondes, integer part sleep duration
n_sleep.tv_nsec =5e8L;//nanoseconds, decimal part sleep duration
char c;
for(c =0; c <128; c++){
printf("char of c :%c\n", c);
printf("ASCII num of c :%d\n", c);
sleep(1);// 1 s
usleep(900000);// 0.9 s
nanosleep(&n_sleep,NULL);// 0 + 0.5 s
}
return0;
}
另外,推荐⼀下clang这款编译器,
它的(1)错误、(2)警告 提⽰⾮常直观、准确、体贴。
⽐如,上⾯的死循环代码,编译之后,它就贴⼼地显⽰了⼀个警告:
result of comparison of constant 128 with expression of type 'char' is always true
[-Wtautological-constant-out-of-range-compare]
for (c = 0; c < 128; c++) {
~ ^ ~~~
强烈推荐啊
当然,如果还是喜欢或者必须使⽤ gcc 的话,建议可以将 clang 作为⼀个辅助选项。
(⼀)sleep函数
头⽂件unistd.h
头⽂件 unistd.h 中的原⽂如下:
/* Make the process sleep for SECONDS seconds, or until a signal arrives
and is not ignored.  The function returns the number of seconds less
than SECONDS which it actually slept (thus zero if it slept the full time).
If a signal handler does a `longjmp' or modifies the handling of the
SIGALRM signal while inside `sleep' call, the handling of the SIGALRM
signal afterwards is undefined.  There is no return value to indicate
error, but if `sleep' returns SECONDS, it probably didn't work.
This function is a cancellation point and therefore not marked with
__THROW.  */
extern unsigned int sleep (unsigned int __seconds);
通过debug的⽅式,进⼊ sleep 函数本体内部,可以反向查到 sleep 函数所在的具体⽂件是 /glibc-2.23/sysdeps/posix/sleep.c 。(根据gcc版本的不同,上⾯的库函数版本号 glibc-2.23 有所不同。)
源⽂件sleep.c
sleep 函数的原型代码如下:
#include<time.h>
#include<unistd.h>
#include<errno.h>
#include<sys/param.h>
/* Make the process sleep for SECONDS seconds, or until a signal arrives
and is not ignored.  The function returns the number of seconds less
than SECONDS which it actually slept (zero if it slept the full time).
If a signal handler does a `longjmp' or modifies the handling of the
SIGALRM signal while inside `sleep' call, the handling of the SIGALRM
signal afterwards is undefined.  There is no return value to indicate
error, but if `sleep' returns SECONDS, it probably didn't work.  */
unsigned int__sleep(unsigned int seconds)
{
int save_errno = errno;
const unsigned int max =
(unsigned int)(((unsigned long int)(~((time_t)0)))>>1);
struct timespec ts ={0,0};
do{
if(sizeof(ts.tv_sec)<=sizeof(seconds)){
/* Since SECONDS is unsigned assigning the value to .tv_sec can
overflow it.  In this case we have to wait in steps.  */
ts.tv_sec +=MIN(seconds, max);
seconds -=(unsigned int)ts.tv_sec;
}else{
ts.tv_sec =(time_t)seconds;
seconds =0;
}
if(__nanosleep(&ts,&ts)<0)
/* We were interrupted.
Return the number of (whole) seconds we have not yet slept.  */
return seconds + ts.tv_sec;
}while(seconds >0);
__set_errno(save_errno);
return0;
}
weak_alias(__sleep, sleep)
sleep函数的⽤法
简单地说, sleep 函数实现的功能是 让程序休眠若⼲秒钟,时间的最⼩刻度是「秒」。
extern unsigned int sleep (unsigned int __seconds);
sleep函数的返回值,
(1)如果 sleep 函数顺利执⾏了的话,返回值是实际休眠的时间数,
(2)如果实际休眠的时间和设定的休眠时间⼀致的话,返回值是0,
(3)不会返回表⽰ 错误 信息的值,但是如果返回的值与设定的休眠时间的值⼀样的话,很可能 sleep 函数其实并没有执⾏,(4)返回值类型是 unsigned int 型,也就是说,是⼀个 ⾮负数 。
sleep函数的参数,
(1)参数的类型是 unsigned int 型,也就是说,是⼀个 ⾮负数 ,
(2)参数的时间单位是 秒 。
所以,sleep函数,使进程/process 休眠的最短时间段,是⼀秒钟。
(⼆)usleep函数
头⽂件unistd.h
头⽂件 unistd.h 中的原⽂如下:
/* Sleep USECONDS microseconds, or until a signal arrives that is not blocked
or ignored.
This function is a cancellation point and therefore not marked with
__THROW.  */
extern int usleep (__useconds_t __useconds);
查上⾯的 sleep.c ⽂件的时候,在 find 命令的结果中看到了 usleep.c ⽂件和 sleep.c ⽂件位于同⼀个⽂件夹:/glibc-2.23/sysdeps/posix/sleep.c 。
(根据gcc版本的不同,上⾯的库函数版本号 glibc-2.23 有所不同。)
源⽂件usleep.c
usleep 函数的原型代码如下:
#include<time.h>
#include<unistd.h>
int
usleep (useconds_t useconds)
{
struct timespec ts ={.tv_sec =(long int)(useconds /1000000),
.tv_nsec =(long int)(useconds %1000000)*1000ul};
/* Note the usleep() is a cancellation point.  But since we call
nanosleep() which itself is a cancellation point we do not have
to do anything here.  */
return __nanosleep (&ts,NULL);
}
名称 usleep 的第⼀个字母 u 代表的是时间单位 微秒 的第⼀个字母。
虽然实际上是希腊字母的 μ ,但英语键盘⾥不⽅便敲出这个字母,所以就⽤了样⼦相似的英⽂字母 u 。
时间单位 微秒 的英⽂单词是 microsecond ,是由词根 micro 和 second 组合⽽成的单词。
微秒 是 10的负6次⽅ 秒。
另外,还有⼀个以字母 m 开头的时间单位的英⽂单词 millisecond ,意思是 毫秒 ,也就是 千分之⼀秒。
注意,区分 micro 和 milli ,⼀个是 微 ,⼀个是 毫 。
usleep函数的⽤法
简单地说, usleep 函数实现的功能是 让程序休眠若⼲「微秒」,时间的最⼩刻度是「微秒」,10的负6次⽅ 秒。/* Sleep USECONDS microseconds, or until a signal arrives that is not blocked
or ignored.
This function is a cancellation point and therefore not marked with
__THROW.  */
extern int usleep (__useconds_t __useconds);
usleep函数的返回值
⽹上查到的是:成功返回0,出错返回-1。
usleep函数的参数
(1) 参数的类型是 __useconds_t ,这个类型的定义要查好⼏个⽂件才得到,
(2) ⾸先是到了头⽂件 types.h ,具体路径是 /glibc/include/sys/types.h ,可惜这⾥⾯没有明确、具体的定义,
(3) 然后还得到头⽂件 typesizes.h ,具体路径是 ==/glibc/sysdeps/mach/hurd/bits/typesizes.h ==,这⾥终于有了,(4) 第⼀个宏, #define __USECONDS_T_TYPE __U32_TYPE ,在 typesizes.h ⽂件⾥,
(5) 第⼆个宏, #define __U32_TYPE unsigned int ,在 types.h ⽂件⾥,
(6) 真是折腾啊!这下总算知道 __useconds_t 就是 unsigned int 类型了,也就是 ⾮负整数。
c语言return的用法和搭配(7) 参数的时间单位是 微秒 。
所以,usleep函数,使进程/process 休眠的最短时间段,是⼀微秒。
(三)nanosleep函数
头⽂件time.h
这个 time.h 头⽂件的路径是 /glibc/time/time.h 。
在C语⾔⾃带的库⽬录⾥⾯,有好⼏个不同⽬录下的 time.h ⽂件,只有这个才是定义了 nanosleep 函数的。
也不知道,编译器在预处理阶段去获取的 time.h 到底是哪个? 或者说,全部都获取过来了?
头⽂件 time.h 中的原⽂如下:
/* Pause execution for a number of nanoseconds.
This function is a cancellation point and therefore not marked with
__THROW.  */
extern int nanosleep (const struct timespec *__requested_time,
struct timespec *__remaining);
函数名称的 nano 是 纳⽶、纳秒 等计量单位的开头字母,⼀纳秒是10的负9次⽅ 秒,是10的负6次⽅ 毫秒,是10的负3次⽅ 微秒。源⽂件nanosleep.c
下⾯是这个路径 /glibc/posix/nanosleep.c 的⽂件内容。
在C语⾔⾃带的函数库中搜索 nanosleep ,出来的结果同样有好⼏个,暂时分不清到底是哪个,先采⽤了这个。
nanosleep 函数的原型代码如下:
#include<errno.h>
#include<time.h>
/* Pause execution for a number of nanoseconds.  */
int
__nanosleep (const struct timespec *requested_time,
struct timespec *remaining)
{
__set_errno (ENOSYS);
return-1;
}
stub_warning (nanosleep)
hidden_def (__nanosleep)
weak_alias (__nanosleep, nanosleep)
nanosleep函数的⽤法
简单地说, nanosleep 函数实现的功能是 让程序休眠若⼲「纳秒」,时间的最⼩刻度是「纳秒」,10的负9次⽅ 秒。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。