可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am just interested how sleep(time in ms)
is implemented in a C library or basically at the OS level...
I am guessing...
- May be the based on the processor speed you do a while loop of nop's (I am not sure if the sleep time will be accurate)...
- Any special register in processor, where you write some value and the processor simply halts for specified time (this would be very inefficient as the processor can't run even other programs).
Any clues? Probably C library source code can explain? I am not too particular about how "C" is implementing it... I am just wondering in general how the "sleep()" function is implemented.
回答1:
Sleep()
is implemented at the OS level. The processor doesn't spin when a task/thread/process is sleeping. That particular thread is put on a pending queue (the thread isn't ready to run) until the time has expired at which point the thread will be placed on the ready to run queue.
In the meantime, other threads that are ready to run will be run.
Only if no threads are ready to run will the OS go into the idle thread, which in generally issues instructions to shutdown (or put into a low-power state anyway) the processor until an hardware interrupt occurs.
Only for a very simple system (like the most simple of embedded systems), might Sleep()
actually be implemented as nothing more than a busy wait loop.
Any operating system textbook, such as "Modern Operating Systems" by Tanenbaum will cover this in great detail - pretty much any of them (even an old, cheap, used one).
回答2:
The answer to your question is completely operating-system and implementation-dependent.
A simple way to think about it: When you call sleep()
, the OS calculates the wakeup time, then sticks your process on a priority queue somewhere. It then just doesn't schedule your process to get any execution time until enough real time has passed for it to get popped off the queue.
回答3:
In a typical operating system, sleep calls into the kernel, which sets the process to wait until the specified amount of time is elapsed, and then goes and finds some other process to run. Absent anything better to do, it will run the 'idle process'. Once the time elapses, the scheduler will note that the sleeping process is good to go, and it will schedule it again.
回答4:
You don't do any while loops, otherwise the system won't be able to do anything - not respond to the mouse, keyboard, network, etc.
Usually what most operating systems do is you add the delay to the current timestamp to get the timestamp when the task that requested the delay will be resumed (assuming there is no higher priority task running at that time) and add the [wakeupTimestamp, task pointer] to a list that is sorted by ascending by the timestamp. After that, the OS performs a context switch and runs the next available task. Periodically, the system compares the earliest timestamp on the sleepy list with the current timestamp, and if the deadline has passed, it moves the sleeping task into the "ready" task queue.
回答5:
Sleep blocks your task/thread for the time value passed. Your task becomes un-runnable for that period or until something else interesting happens (like a signal), whichever is sooner.
It is not uncommon for sleep to call select() and pass no descriptors to wait on and a timeout value equal to your sleep period.
The system may implement this by setting a timer to expire after the time passed and then waiting on a semaphore that will be signalled when that timer expires. Thus it is blocked on that semaphore.
回答6:
cpu usage: 0%
requirements:
create_gate (Set up the IRQ handlers)
pic_mask_clear (Enable specific interrupts)
rtc_poll (Set up 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
usage :
mov rax, 1000 (millisecond)
call sleep
its fine