In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly explains "the time management and timer principle of linux". Interested friends may wish to have a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn the time management and timer principle of linux.
When linux is initialized, the timing-related code is initialized.
Void sched_init (void)
{
...
/ / 43 is the control word port, 0x36=0x00110110, that is, binary, mode 3, read and write low 8 bits and then read write high 8 bits, select calculator 0
Outb_p (0x36 mode 0x43); / * binary, mode 3, LSB/MSB, ch 0 * /
/ *
Write the initial value, port 40 is the count channel 0, the initial value
The meaning of 8253 is that for each fluctuation, the initial value is reduced by one, and when it is reduced to 0, a notification is output.
LATCH = (1193180amp 100), 1193180 is the operating frequency of 8253
It fluctuates 1193180 times a second. (1193180hip 100) is (1193180Universe 1000) * 10, that is,
1 millisecond elapsed when it dropped to zero. Multiplied by 10 is the past 10 milliseconds.
, /
Outb_p (LATCH & 0xff, 0x40); / * LSB * /
/ / write another 8 digits
Outb (LATCH > > 8, 0x40); / * MSB * /
/ / set the timing interrupt handler. The interrupt number is 200.8253, which will trigger the interrupt.
Set_intr_gate (0x20 camera timerbroken)
...
}
_ timer_interrupt:
Push ds # save ds,es and put kernel data space
Push% es # into them. % fs is used by _ system_call
Push fs
Pushl edx # we save eax,%ecx,%edx as gcc doesn't
Pushl% ecx # save those across function calls. % ebx
Pushl ebx # is saved as we use that in ret_sys_call
Pushl eax
Movl $0x10pen% eax
Mov ax,%ds
Mov ax,%es
Movl $0x17pen% eax
Mov ax,%fs
Incl _ jiffies
Movb $0x20J% al # EOI to interrupt controller # 1
Outb al,$0x20
Movl CS (% esp),% eax
Andl $3tech% eax #% eax is CPL (0 or 3, 0=supervisor)
Pushl eax
Call _ do_timer # 'do_timer (long CPL)' does everything from
Addl $4J% esp # task switching to accounting...
Jmp ret_from_sys_call
When we see an interrupt, we execute the do_timer function, which handles timers and process scheduling. Before that, let's take a look at how to add a timer.
# define TIME_REQUESTS 64
/ / timer array, which is actually a linked list
Static struct timer_list {
Long jiffies
Void (* fn) ()
Struct timer_list * next
} timer_ list [time _ REQUESTS], * next_timer = NULL
Void add_timer (long jiffies, void (* fn) (void))
{
Struct timer_list * p
If (! fn)
Return
/ / off interrupt to prevent multiple processes from operating at the same time
Cli ()
/ / expire directly and execute callback directly
If (jiffies fn)
Break
/ / there are no empty items
If (p > = timer_list + TIME_REQUESTS)
Panic ("No more time requests free")
/ / assign a value to an empty item
P-> fn = fn
P-> jiffies = jiffies
/ / form a linked list in an array
P-> next = next_timer
/ / next_timer points to the first node, that is, the earliest to expire
Next_timer = p
/ *
Modify the linked list to ensure that the timeout is in the order from small to large.
Principle:
Each node takes the arrival time of the previous node as the coordinate, and the jiffies in the node is the timeout.
Is the number of jiffies after the previous node expires after that node expires.
, /
While (p-> next & & p-> next- > jiffies
< p->Jiffies) {
/ / if the front node is larger than the back node, the front node subtracts the value of the back node, calculates the offset value, and prepares the replacement position.
P-> jiffies-= p-> next- > jiffies
/ / save it first.
Fn = p-> fn
/ / callback for replacing two nodes
P-> fn = p-> next- > fn
P-> next- > fn = fn
Jiffies = p-> jiffies
/ / replacement of two nodes is a timeout
P-> jiffies = p-> next- > jiffies
P-> next- > jiffies = jiffies
/ *
At this point, the first node is the fastest to expire, and the value of the subsequent node needs to be updated, which is to find a suitable location.
Insert, because the kernel is a timer queue implemented by an array, it is inserted by replacing the position.
If it is a linked list, then directly find the appropriate location, insert it, the so-called appropriate position
Is to find the first node larger than the current node and insert it in front of him.
, /
P = p-> next
}
/ *
The kernel implementation has a bug. When the current node is minimum, the value of the first node in the original linked list needs to be updated.
Otherwise, the expiration time of the first node in the original linked list will be prolonged. The repair code is as follows:
If (p-> next & & p-> next- > jiffies > p-> jiffies) {
P-> next- > jiffies = p-> next- > jiffies-p-> jiffies
}
That is, to update the offset of the first node in the original linked list relative to the new first node, the remaining node does not need to be updated because it is relative to the
The offset of the node in front of him remains the same, but there is no node before the first node in the original linked list, so the offset is his own value.
Now that a node is inserted in front of him, his offset is relative to the previous node.
, /
}
Sti ()
}
The above is an example diagram. This completes the insertion of the timing node. Let's look back at the do_timer code, that is, the code that the system executes when it is interrupted by timing.
Void do_timer (long cpl)
{
...
/ / currently in the user mode, increase the execution time of the user mode, otherwise increase the system execution time of the process
If (cpl)
Current- > utime++
Else
Current- > stime++
/ / empty next_timer means there is no timing node yet.
If (next_timer) {
/ / the first node subtracts a jiffies, because the other nodes are offset from the first node, so the values of the other nodes do not need to be changed.
Next_timer- > jiffies--
/ / the current node expires. If the timeout period of multiple nodes is the same, that is, the offset from the first node is 0, the while loop will be entered many times.
While (next_timer & & next_timer- > jiffies fn)
Next_timer- > fn = NULL
Next_timer = next_timer- > next
(fn) ()
}
}
...
/ / process scheduling
Schedule ()
}
We find that add_timer has calculated that the order of timers expires from first to then, and the later node is offset from the previous node, so when you judge the timeout, you only need to judge from the destination. If the first node does not expire, the later node will not expire. If the first node expires, you will continue to judge the next node. Put time-consuming operations to new nodes, because new operations are rare and infrequent, but scheduled interruptions are frequent. So this ensures performance. Finally, we also found that this is where the operating system handles process scheduling through the schedule function. That is, less than 10 milliseconds, the system process is scheduled at one time.
At this point, I believe you have a deeper understanding of "linux time management and timer principle", might as well come to the actual operation of it! Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.