睡眠与唤醒 (草稿)
1. 调用 nanosleep() 以后发生了什么?
nonosleep() 是一个系统调用,在内核中对应的是 sys_nonosleep()
sys_nonosleep:
创建一个定时器
struct hrtimer_sleeper {
struct hrtimer timer;
struct task_struct *task;
};
void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, struct task_struct *task)
{
sl->timer.function = hrtimer_wakeup;
sl->task = task;
}
定时器的处理函数设置为 hrtimer_wakeup()
将当前进程状态设置为TASK_INTERRUPTIBLE
启动定时器
调用 schedule(),主动进行进程调度,放弃控制权
Schedule() 检查当前进程,发现是TASK_INTERRUPTIBLE,就把它从执行队列中删除。因此,现在这个进程已经不属于任何队列了,那么到哪能找到它了?对,通过定时器还能找到它。另外,还可以根据 PID ,从 pidhash[] 中找到这个进程。
2. 时间到了以后如何唤醒进程?
static int hrtimer_wakeup(struct hrtimer *timer)
{
struct hrtimer_sleeper *t =
container_of(timer, struct hrtimer_sleeper, timer);
struct task_struct *task = t->task;
t->task = NULL;
if (task)
wake_up_process(task);
return HRTIMER_NORESTART;
}
从定时器中得到对应的 task,然后通过 wake_up_process(),又把这个进程设置为 RUNNING,并加入到可执行队列中。
3. Sleep 期间为什么能处理信号?
这就是TASK_INTERRUPTIBLE 和TASK_UNINTERRUPTIBLE 的区别,对于通过 nanosleep() 这种方式进入睡眠的进程,是可以被信号打断的,当信号到来时,进程会被设置为可运行
if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&
unlikely(signal_pending(prev))))
prev->state = TASK_RUNNING;
1. 调用 nanosleep() 以后发生了什么?
nonosleep() 是一个系统调用,在内核中对应的是 sys_nonosleep()
sys_nonosleep:
创建一个定时器
struct hrtimer_sleeper {
struct hrtimer timer;
struct task_struct *task;
};
void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, struct task_struct *task)
{
sl->timer.function = hrtimer_wakeup;
sl->task = task;
}
定时器的处理函数设置为 hrtimer_wakeup()
将当前进程状态设置为TASK_INTERRUPTIBLE
启动定时器
调用 schedule(),主动进行进程调度,放弃控制权
Schedule() 检查当前进程,发现是TASK_INTERRUPTIBLE,就把它从执行队列中删除。因此,现在这个进程已经不属于任何队列了,那么到哪能找到它了?对,通过定时器还能找到它。另外,还可以根据 PID ,从 pidhash[] 中找到这个进程。
2. 时间到了以后如何唤醒进程?
static int hrtimer_wakeup(struct hrtimer *timer)
{
struct hrtimer_sleeper *t =
container_of(timer, struct hrtimer_sleeper, timer);
struct task_struct *task = t->task;
t->task = NULL;
if (task)
wake_up_process(task);
return HRTIMER_NORESTART;
}
从定时器中得到对应的 task,然后通过 wake_up_process(),又把这个进程设置为 RUNNING,并加入到可执行队列中。
3. Sleep 期间为什么能处理信号?
这就是TASK_INTERRUPTIBLE 和TASK_UNINTERRUPTIBLE 的区别,对于通过 nanosleep() 这种方式进入睡眠的进程,是可以被信号打断的,当信号到来时,进程会被设置为可运行
if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&
unlikely(signal_pending(prev))))
prev->state = TASK_RUNNING;