4.用户态睡眠
以sleep为例来说明任务在用户态是如何睡眠的。
首先我们通过strace工具来看下其调用的系统调用:
$ strace sleep 1
...
close(3) = 0
clock_nanosleep(CLOCK_REALTIME, 0, {
tv_sec=1, tv_nsec=0}, NULL) = 0
close(1) = 0
...
可以发现sleep主要调用clock_nanosleep系统调用来进行睡眠(也就是说用户态任务睡眠需要调用系统调用陷入内核)。
下面我们来研究下clock_nanosleep的实现(这里集中到睡眠的实现,先忽略掉定时器等诸多的技术细节):
kernel/time/posix-timers.c
SYSCALL_DEFINE4(clock_nanosleep
->const struct k_clock *kc = clockid_to_kclock(which_clock); //根据时钟类型得到内核时钟结构
return kc->nsleep(which_clock, flags, &t); //调用内核时钟结构的nsleep回调
我们传递过来的时钟类型为CLOCK_REALTIME,则调用链为:
kc->nsleep(CLOCK_REALTIME, flags, &t)
->clock_realtime.nsleep
->common_nsleep
->hrtimer_nanosleep