nanosleep()则是Linux中的系统调用,它是使用定时器来实现的,该调用使调用进程睡眠,并往定时器队列上加入一个hrtimer型定时器,time_list结构里包括唤醒时间以及唤醒后执行的函数,通过nanosleep()加入的定时器的执行函数仅仅完成唤醒当前进程的功能。系统通过一定的机制定时检查这些队列(比如通过系统调用陷入核心后,从核心返回用户态前,要检查当前进程的时间片是否已经耗尽,如果是则调用schedule()函数重新调度,该函数中就会检查定时器队列,另外慢中断返回前也会做此检查),如果定时时间已超过,则执行定时器指定的函数唤醒调用进程。当然,由于系统时间片可能丢失,所以nanosleep()精度也不是很高。
内核实现nanosleep的函数是compat_sys_nanosleep:
asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp, //rqtp是要暂停的时间。
struct compat_timespec __user *rmtp) //rmtp是距下次唤醒的时间。
{
struct timespec tu, rmt;
mm_segment_t oldfs;
long ret;
if (get_compat_timespec(&tu, rqtp))
return -EFAULT;
if (!timespec_valid(&tu))
return -EINVAL;
oldfs = get_fs();
set_fs(KERNEL_DS);
/*
*函数的核心
*/
ret = hrtimer_nanosleep(&tu,
rmtp ? (struct timespec __user *)&rmt : NULL,
HRTIMER_MODE_REL, CLOCK_MONOTONIC);
set_fs(oldfs);
if (ret) {
struct restart_block *restart
= ¤t_thread_info()->restart_block;
restart->fn = compat_nanosleep_restart;
restart->nanosleep.compat_rmtp = rmtp;
if (rmtp && put_compat_timespec(&rmt, rmtp))
return -EFAULT;
}
return ret;
}
来看这个函数中的核心操作hrtimer_nanosleep():
long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
const enum hrtimer_mode mode, const clockid_t clockid)
{
struct restart_block *restart;
struct hrtimer_sleeper t;
int ret = 0;
unsigned long slack;
slack = current->timer_slack_ns;
if (rt_task(current)) //如果当前进程是rt任务,那么时间松弛度是0.
slack = 0;
/*
*初始化一个hrtimer
*/
hrtimer_init_on_stack(&t.timer, clockid, mode);
hrtimer_set_expires_range_ns(&t.timer, timespec_to_ktime(*rqtp), slack);
if (do_nanosleep(&t, mode))
goto out;
/* Absolute timers do not update the rmtp value and restart: */
if (mode == HRTIMER_MODE_ABS) {
ret = -ERESTARTNOHAND;
goto out;
}
if (rmtp) {
ret = update_rmtp(&t.timer, rmtp);
if (ret <= 0)
goto out;
}
restart = ¤t_thread_info()->restart_block;
restart->fn = hrtimer_nanosleep_restart;
restart->nanosleep.clockid = t.timer.base->clockid;
restart->nanosleep.rmtp = rmtp;
restart->nanosleep.expires = hrtimer_get_expires_tv64(&t.timer);
ret = -ERESTART_RESTARTBLOCK;
out:
destroy_hrtimer_on_stack(&t.timer);
return ret;
}
首先,要初始化一个hrtimer,调用hrtimer_init_on_stack(&t.timer, clockid, mode),最终调用__hrtimer_init():
static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
enum hrtimer_mode mode)
{
struct hrtimer_cpu_base *cpu_base;
int base;
memset(timer, 0, sizeof(struct hrtimer));
cpu_base = &__raw_get_cpu_var(hrtimer_bases);
if (clock_id == CLOCK_REALTIME && mode != HRTIMER_MODE_ABS)
clock_id = CLOCK_MONOTONIC;
base = hrtimer_clockid_to_base(clock_id);
timer->base = &cpu_base->clock_base[base];
ti