如何在操作系统级别实现睡眠?

我只是感兴趣的是如何在C库或基本上在操作系统级别实现sleep(time in ms)为单位的sleep(time in ms) ……

我猜…

  1. 可能是基于处理器速度你做了一段时间的nop循环(我不确定睡眠时间是否准确)…
  2. 处理器中的任何特殊寄存器,您可以在其中写入一些值,处理器只会暂停指定的时间(由于处理器甚至无法运行其他程序,因此效率非常低)。

有什么线索吗? 可能C库的源代码可以解释一下吗? 我并不太关注“C”是如何实现的……我只是想知道“sleep()”函数是如何实现的。

Sleep()在OS级别实现。 当任务/线程/进程正在hibernate时,处理器不会旋转。 该特定线程被置于挂起队列(线程尚未准备好运行),直到时间到期为止,此时线程将被置于准备运行队列中。

与此同时,将运行准备运行的其他线程。

只有当没有线程准备好运行时,操作系统才会进入空闲线程,这通常会发出指令以关闭(或无论如何都处于低功耗状态)处理器,直到硬件中断发生。

仅对于一个非常简单的系统(如最简单的嵌入式系统), Sleep()实际上可以实现为繁忙的等待循环。

任何操作系统教科书,例如Tanenbaum的“现代操作系统”都将非常详细地介绍它 – 几乎任何一本(甚至是旧的,便宜的,用过的)。

您的问题的答案完全取决于操作系统和实现。

考虑它的一种简单方法:当您调用sleep() ,操作系统会计算唤醒时间,然后将您的进程粘贴到某个优先级队列中。 然后,它不会安排您的进程获得任何执行时间,直到有足够的实时时间将其从队列中弹出。

在典型的操作系统中,sleep调用内核,将进程设置为等到指定的时间量过去,然后继续查找要运行的其他进程。 没有更好的事情,它将运行’空闲过程’。 一旦时间流逝,调度程序将注意到睡眠过程是好的,它将再次安排它。

你不做任何循环,否则系统将无法做任何事情 – 不响应鼠标,键盘,网络等。

通常,大多数操作系统所做的是将延迟添加到当前时间戳以获取请求延迟的任务将被恢复时的时间戳(假设此时没有运行更高优先级的任务)并添加[wakeupTimestamp,任务指针]到按时间戳升序排序的列表。 之后,OS执行上下文切换并运行下一个可用任务。 系统会定期将睡眠列表中最早的时间戳与当前时间戳进行比较,如果截止日期已过,则将睡眠任务移动到“就绪”任务队列。

Sleep会阻止您的任务/线程传递时间值。 你的任务在那段时间内变得无法运行,或直到其他有趣的事情发生(如信号),以较早者为准。

睡眠调用select()并传递没有描述符等待并且超时值等于您的睡眠时间并不罕见。

系统可以通过将计时器设置为在经过一段时间之后到期,然后等待将在该计时器到期时发出信号的信号量来实现这一点。 因此它在该信号量上被阻止。

CPU使用率:0%
要求:

create_gate(设置IRQ处理程序)
pic_mask_clear(启用特定中断)
rtc_poll(设置RTC)
rtc_irq
smp_wake_up

 ; In\ RAX = Time in millisecond ; Out\ All registers preserved sleep: push rcx push rax mov rcx, [rtc_irq.up_time] add rax, rcx .os_delay_loop: hlt cmp qword [rtc_irq.up_time], rax jle .os_delay_loop pop rax pop rcx ret 

smp_wake_up

 ; In\ Nothing ; Out\ Nohting smp_wakeup_all: push rdi push rax mov rdi, [os_LocalAPICAddress] xor eax, eax mov [rdi+0x0310], eax ; Write to the high bits first mov eax, 0x000C0080 ; Execute interrupt 0x80 mov [rdi+0x0300], eax ; Then write to the low bits pop rax pop rdi ret 

rtc_irq:

 ; UIP (0), RTC@32.768KHz (010), Rate@1024Hz (0110) ; In\ Nothing ; Out\ Nothing rtc_irq: inc qword[.up_time] call smp_wakup_all ret .up_time: dq 0 

用法:

 mov rax, 1000 (millisecond) call sleep 

没关系