Как реализован режим сна на уровне ОС? - PullRequest
24 голосов
/ 12 ноября 2009

Мне просто интересно, как sleep(time in ms) реализован в библиотеке C или в основном на уровне ОС ...

Я думаю ...

  1. Может быть в зависимости от скорости процессора, которую вы выполняете во время цикла nop (я не уверен, что время сна будет точным) ...
  2. Любой специальный регистр в процессоре, где вы записываете какое-то значение, и процессор просто останавливается на указанное время (это было бы очень неэффективно, поскольку процессор не может запускать даже другие программы).

Есть какие-нибудь подсказки? Возможно исходный код библиотеки C может объяснить? Я не слишком разбираюсь в том, как это реализует «C» ... Мне просто интересно узнать, как реализована функция «sleep ()».

Ответы [ 6 ]

19 голосов
/ 12 ноября 2009

Sleep() реализовано на уровне ОС. Процессор не вращается, когда задача / поток / процесс спит. Этот конкретный поток помещается в очередь ожидания (поток не готов к запуску) до тех пор, пока не истечет время, в которое поток будет помещен в очередь готовности к запуску.

Тем временем будут запущены другие готовые к работе потоки.

Только если ни один из потоков не готов к работе, ОС перейдет в незанятый поток, который обычно выдает инструкции по отключению (или переводу в состояние с низким энергопотреблением) процессора до тех пор, пока не произойдет аппаратное прерывание.

Только для очень простой системы (например, самой простой встраиваемой системы) Sleep() может быть реализовано в виде не более чем занятого цикла ожидания.

Любой учебник по операционной системе, такой как «Современные операционные системы» от Tanenbaum , подробно расскажет об этом - практически любой из них (даже старый, дешевый, использованный).

2 голосов
/ 12 ноября 2009

В типичной операционной системе sleep вызывает ядро, которое заставляет процесс ждать, пока не истечет указанное количество времени, а затем отправляется и находит какой-то другой процесс для запуска. Если нет ничего лучше, он будет запускать «простой процесс». По истечении этого времени планировщик заметит, что спящий процесс можно начинать, и снова запланирует его.

2 голосов
/ 12 ноября 2009

Ответ на ваш вопрос полностью зависит от операционной системы и реализации.

Простой способ думать об этом: когда вы вызываете sleep(), ОС вычисляет время пробуждения, а затем помещает ваш процесс в очередь с приоритетами. Затем он просто не планирует ваш процесс для получения какого-либо времени выполнения до тех пор, пока не пройдет достаточно реального времени для его выталкивания из очереди.

1 голос
/ 12 ноября 2009

Сон блокирует вашу задачу / поток за прошедшее время. Ваша задача становится невыполнимой в течение этого периода или до тех пор, пока не произойдет что-то интересное (например, сигнал), в зависимости от того, что произойдет раньше.

Нередко для режима сна вызывается метод select () и не передаются никакие дескрипторы для ожидания, а значение времени ожидания равно периоду ожидания.

Система может реализовать это, установив время истечения таймера после истечения времени, а затем ожидая семафора, который будет сигнализироваться по истечении этого таймера. Таким образом, он заблокирован на этом семафоре.

1 голос
/ 12 ноября 2009

Вы не делаете никаких циклов while, иначе система не сможет ничего сделать - не реагировать на мышь, клавиатуру, сеть и т. Д.

Обычно в большинстве операционных систем вы добавляете задержку к текущей метке времени, чтобы получить метку времени, когда задача, которая запросила задержку, будет возобновлена ​​(при условии, что в это время не выполняется задача с более высоким приоритетом) и добавляете [wakeupTimestamp. , указатель задачи] на список, отсортированный по возрастанию по метке времени. После этого ОС выполняет переключение контекста и запускает следующую доступную задачу. Периодически система сравнивает самую раннюю временную метку в списке сонных режимов с текущей временной меткой, и если крайний срок прошел, она перемещает спящую задачу в очередь «готовых» задач.

0 голосов
/ 27 марта 2018

загрузка процессора: 0%требования:

create_gate (настройка обработчиков IRQ)pic_mask_clear (включить определенные прерывания)rtc_poll (настроить RTC)rtc_irqsmp_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

штраф

...