38

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

我猜...

  1. 可能是基于处理器速度你做一个nop的while循环(我不确定睡眠时间是否准确)......
  2. 处理器中的任何特殊寄存器,您在其中写入一些值并且处理器只是在指定的时间内停止(这将非常低效,因为处理器甚至无法运行其他程序)。

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

4

6 回答 6

30

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

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

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

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

任何操作系统教科书,例如Tanenbaum 的“现代操作系统”,都会非常详细地介绍这一点——几乎所有教科书(甚至是旧的、便宜的、用过的)。

于 2009-11-12T00:38:14.150 回答
3

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

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

于 2009-11-12T00:38:55.163 回答
3

在典型的操作系统中,sleep 调用内核,它将进程设置为等待直到指定的时间量过去,然后去寻找其他一些要运行的进程。如果没有更好的事情要做,它将运行“空闲进程”。一旦时间过去,调度器会注意到正在休眠的进程是好的,它会再次调度它。

于 2009-11-12T00:39:06.643 回答
1

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

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

于 2009-11-12T00:38:57.690 回答
1

睡眠会阻塞您的任务/线程以获取传递的时间值。您的任务在此期间无法运行,或者直到发生其他有趣的事情(如信号),以较早者为准。

sleep 调用 select() 并且不传递要等待的描述符并且超时值等于您的睡眠时间的情况并不少见。

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

于 2009-11-12T08:37:48.487 回答
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

没关系

于 2018-03-27T13:43:32.310 回答