Как реализован режим сна на уровне ОС?

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

Я предполагаю, что...

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

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

6 ответов

Решение

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

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

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

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

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

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

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

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

Загрузка процессора: 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

все в порядке

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

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

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

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

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

Другие вопросы по тегам