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

时间:2009-11-12 00:32:58

标签: c operating-system sleep

我只是对{C}库中实现sleep(time in ms)或基本上在操作系统级别实现的感兴趣......

我在猜...

  1. 可能是基于处理器速度你做了一段时间的nop循环(我不确定睡眠时间是否准确)...
  2. 处理器中的任何特殊寄存器,您可以在其中写入一些值,处理器只会停止指定的时间(由于处理器甚至无法运行其他程序,因此效率非常低)。
  3. 任何线索?可能C库的源代码可以解释一下吗?我并不太关注“C”是如何实现的......我只是想知道“sleep()”函数是如何实现的。

6 个答案:

答案 0 :(得分:19)

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

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

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

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

任何操作系统教科书,例如"Modern Operating Systems" by Tanenbaum都将非常详细地介绍它 - 几乎任何一本教科书(即使是旧的,便宜的,用过的)。

答案 1 :(得分:2)

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

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

答案 2 :(得分:2)

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

答案 3 :(得分:1)

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

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

答案 4 :(得分:1)

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

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

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

答案 5 :(得分:-1)

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

很好