Как реализован режим сна на уровне ОС?
Мне просто интересно как sleep(time in ms)
реализуется в библиотеке C или в основном на уровне ОС...
Я предполагаю, что...
- Может быть, в зависимости от скорости процессора вы делаете цикл while из nop (я не уверен, будет ли точное время сна)...
- Любой специальный регистр в процессоре, где вы записываете какое-то значение, а процессор просто останавливается на указанное время (это было бы очень неэффективно, поскольку процессор не может запускать даже другие программы).
Есть какие-нибудь подсказки? Возможно исходный код библиотеки 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() и не передаются никакие дескрипторы для ожидания, а значение времени ожидания равно периоду ожидания.
Система может реализовать это, установив таймер на истечение времени после истечения времени, а затем ожидая семафора, который будет сигнализироваться по истечении этого таймера. Таким образом, он заблокирован на этом семафоре.