我们介绍nanosleep()和pause()两个系统调用。
系统调用nanosleep()在内核中的实现为sys_nanosleep(),代码如下:
asmlinkage long sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp)//第一个指针rqtp指向给定所需睡眠时间的数据结构;第二个指针rmtp,指向返回剩余时间的数据结构
{
struct timespec t;
unsigned long expire;
if(copy_from_user(&t, rqtp, sizeof(struct timespec)))//所需睡眠时间从用户空间复制到内核空间
return -EFAULT;
if (t.tv_nsec >= 1000000000L || t.tv_nsec < 0 || t.tv_sec < 0)
return -EINVAL;
if (t.tv_sec == 0 && t.tv_nsec <= 2000000L &&
current->policy != SCHED_OTHER)//由于时钟中断只能达到10毫秒的精度,如果要求睡眠的时间小于2毫秒,而要求睡眠的进程又是个实时要求的进程,那就不能真的让这个进程进入睡眠,因为那样有可能10毫秒以后才能将其唤醒,对于实时进程来说是不能接受的
{
/*
* Short delay requests up to 2 ms will be handled with
* high precision by a busy wait for all real-time processes.
*
* Its important on SMP not to do this holding locks.
*/
udelay((t.tv_nsec + 999) / 1000);//延迟两秒
return 0;
}
expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec);//将数据结构t中的数值换算成时钟中断的次数
current->state = TASK_INTERRUPTIBLE;//将当期进程的状态设置为TASK_INTERRUPTIBLE
expire = schedule_timeout(expire);//让当期进程睡眠给定的时间;返回剩余的时钟中断次数,如果没有,返回0
if (expire) {
if (rmtp) {
jiffies_to_timespec(expire, &t);//剩余的时钟中断次数转换成数据结构t的数值
if (copy_to_user(rmtp, &t, sizeof(struct timespec)))//剩余时间从内核空间复制到用户空间
return -EFAULT;
}
return -EINTR;
}
return 0;
}
schedule_timeout,让当期进程睡眠给定的时间,代码如下:
signed long schedule_timeout(signed long timeout)
{
struct timer_list timer;
unsigned long expire;
switch (timeout)
{
case MAX_SCHEDULE_TIMEOUT:
/*
* These two special cases are useful to be comfortable
* in the caller. Nothing more. We could take
* MAX_SCHEDULE_TIMEOUT from one of the negative value
* but I' d like to return a valid offset (>=0) to allow
* the caller to do everything it want with the retval.
*/
schedule();//无限期等待
goto out;
default:
/*
* Another bit of PARANOID. Note that the retval will be
* 0 since no