概述
linux 系统下的休眠函数主要有两个,sleep,nanosleep;usleep 已经被遗弃;sleep,nanosleep休眠都是基于实时时钟(比如挂钟,墙钟,手表,国家授时时间)的sleep,两种sleep方式都受信号中断影响,调用进程捕捉到一个信号并从信号处理程序返回(nanosleep返回未休眠完的秒数)。信号会对所在进程产生中断,同时sleep退出,比如SIGALRM,或系统通知进程的信号,都会导致sleep的退出,导致没有达到相关的预期。
直接使用sleep,nanosleep需要考虑中断的因素,避免和定时器的SIGALRM冲突,减少sleep的中断,定时器避免使用
ITIMER_REAL(SIGALRM)方式和ITIMER_PROF(SIGPROF),尽量采用ITIMER_VIRTUAL方式。
另外采用退出继续sleep的方法:
void myMsleep(unsigned int mSec)
{
unsigned int interrupt_cnk = 0;
struct timespec req = {0};
req.tv_sec = mSec / 1000;
req.tv_nsec = (mSec % 1000) * 1000000;
while (nanosleep(&req, &req) < 0 && errno == EINTR)
{
if(errno == EINTR)
{
interrupt_cnk ++;
}
}
if(interrupt_cnk > 0)
{
printf("myMsleep[%d]ms interruupt_cnk:%dn",mSec,interrupt_cnk);
}
}
随着多系统时钟的引入,我们需要一种方法来挂起调用线程,使用一个运行时钟来实现一段延时,函数clock_nanosleep实现了这一功能,解决被中断退出的问题。
int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *reqtp, struct timespec *remtp);
参数clock_id用于指定延时是相对于哪一种时钟时间进行的评估。参数flags用于控制延时是绝对的还是相对的,
当flags被设置为0的时候,睡眠时间是相对的,当其数值被设置为TIMER_ABSTIME的时候,睡眠时间是绝对的,直到时钟到达指定的时间才返回。
当设置为绝对延时参数remtp是没有被使用的。参数reqtp以及remtp,与函数nanosleep相同。
CLOCK_REALTIME:实时系统时钟,以相对时间为准,从1970.1.1到目前的时间,更改系统时间会更改获取的值,硬件定时中断产生。
CLOCK_MONOTONIC:实时系统时钟,以绝对时间为准,获取的时间为系统重启到现在的时间,更改系统时间对它没有影响硬件定时中断产生。
CLOCK_PROCESS_CPUTIME_ID:系统运行时钟,运行周期计时。
CLOCK_THREAD_CPUTIME_ID:线程运行时钟,运行周期计时。
调用clock_nanosleep(CLOCK_REALTIME, 0, reqtp, remtp);
与如下调用有着完全相同的作用
nanosleep(reqtp, remtp);
可以使用while(clock_nanosleep(CLOCK_PROCESS_CPUTIME_ID,0,&req, &req)< 0 && errno == EINTR) 或
while(clock_nanosleep(CLOCK_MONOTONIC,0,&req, &req)< 0 && errno == EINTR)替代nanosleep用例,
但是由于CLOCK_PROCESS_CPUTIME_ID是进程的可运行时钟周期,所以本进程不能进入休眠状态,并且由于本进程的CPU调度关系,所以期望和预设的值差别比较大!也需要慎用!
测试发现,休眠没有被定时中断退出的情况。
休眠的另一种方式线程等待:pthread_cond_timedwait
int threadSleep(unsigned int msec)
{
pthread_cond_t cond;
pthread_mutex_t mutex;
pthread_condattr_t cattr;
struct timeval now;
struct timespec waittime;
int ret = -1;
long nsec = 0;
pthread_mutex_init(&mutex, NULL);
pthread_condattr_init(&cattr);
pthread_condattr_setclock(&cattr, CLOCK_MONOTONIC);
pthread_cond_init(&cond, &cattr);
clock_gettime(CLOCK_MONOTONIC, &waittime);
nsec = waittime.tv_nsec + (msec * 1000) * 1000;
waittime.tv_sec += nsec / 1000000000;
waittime.tv_nsec = nsec % 1000000000;
pthread_mutex_lock(&mutex);
ret = pthread_cond_timedwait(&cond, &mutex, &waittime);
pthread_mutex_unlock(&mutex);
return ret;
}
注意:特别小心使用CLOCK_REALTIME方式休眠,避免因为系统调整时间回退导致的无法退出的问题;另外在while或for的死循环里,需要考虑内核系统运行调度周期,尽量避免nanosleep小于这个周期,导致系统高频率的运行调度导致的CPU的性能损耗。
最后
以上就是故意毛巾为你收集整理的linux 系统下的休眠应用的全部内容,希望文章能够帮你解决linux 系统下的休眠应用所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复