Linux延时函数

前言
代码编写经常会涉及到延时处理,而Linux环境下系统最常用的延时函数不过如下几个sleep/usleep/nanosleep,分别提供秒级、微秒级、纳秒级延时功能,这几个函数我们几乎天天都在使用,但我们是否准确安全的使用了他们?
 
先来看一下几个函数的原型:
unsigned int sleep(unsigned int seconds);
int usleep(useconds_t usec);
int nanosleep(const struct timespec *req, struct timespec *rem);
 
useconds_t在linux中的定义就是unsigned int
struct timespec {
        time_t  tv_sec;         /* seconds */
        long    tv_nsec;        /* nanoseconds */
};
 
1、 sleep函数可能提前返回,即延时时间不足seconds秒
原因分析:sleep函数可能被信号中断而提前返回
规避措施:判断sleep的返回值,只有返回0时才表示完成预期的延时,否则返回剩余的秒数。所以请检查一下您的代码中是否判断了sleep的返回值?
 
2、 usleep/nansleep函数成功返回时其延时时间可能大于入参指定的时间
原因分析:usleep函数手册中明确标示usleep调用至少挂起进程usec微秒,导致进程挂起时间变长的原因是:
1、  函数调用的开销
2、  系统调度开销
3、  系统定时器的精度
规避措施:
1、  一定要判定usleep的返回值,仅当返回0表示成功
2、  在时间精度要求比较高的场合不建议使用usleep函数
 
3、 usleep函数不能用于秒级以上的延时
原因分析: 在某些系统中usleep接受的入参最大值必须小于1000000(即1秒)
规避措施:
1、  用sleep函数替代
2、  通过多次usleep完成
3、  其他
说明:在Suse9/10上测试是没有问题的,但出于可移植性考虑,不要使用usleep作秒级以上的延时
 
4、nanosleep函数延时存在多种情况,需要根据返回值/errno/输出变量综合判断
情况1延时时间大于或是等于预期时间(绝大部分情况下),返回0
情况2延时时间小于预期时间,返回-1
情况2.1 errno为EINTR表示函数提前返回,此时可读取第2个参数的获取剩余时间
情况2.2 errno为EINVAL表示第一个入参req.tv_nsec取值超出范围[0, 999,999,999]
 
后记
简简单单一个延时函数的使用,就存在这么多需要关注的细节,看来千里之堤毁于蚁穴并非危言耸听(我们至少有70%代码中没有判断延时函数的返回值)。每个健壮的系统、每项高精尖的技术肯定离不开这些细节的处理。对于软件开发而言,要处理好这些细节,简言之就是标准动作做标准(这些在编程规范中都有要求)
1、  了解你的系统、接口、库函数,仔细的查看帮助文档、手册
2、  全面的检查返回值、环境变量、输出输出参数

你可能感兴趣的:(Linux)