In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
In this article, the editor introduces in detail "what is the sleep and awakening method of the Linux process", the content is detailed, the steps are clear, and the details are handled properly. I hope that this article "what is the sleep and awakening method of the Linux process" can help you solve your doubts.
In Linux, processes that wait only for CPU time are called ready processes, and they are placed in a running queue, and the status flag of a ready process is TASK_RUNNING. Once a running process time slice runs out, the Linux kernel scheduler deprives the process of control of the CPU and selects an appropriate process from the run queue to run.
Of course, a process can also actively release control of CPU. The function schedule () is a scheduling function that can be actively called by one process to schedule other processes to occupy CPU. Once the process that actively abandons CPU is rescheduled to occupy CPU, it will execute from the location where execution was last stopped, that is, from the next line of code that calls schedule (). Sometimes, the process needs to wait until a specific event occurs, such as the completion of device initialization, the completion of the Iwhite O operation, or the arrival of a timer. In this case, the process must be removed from the run queue and added to a waiting queue, when the process goes to sleep.
Classification of process Sleep State in Linux
One is an interruptible sleep state in which the status marker bit TASK_INTERRUPTIBLE
The other is the uninterruptible sleep state, whose status marker bit is TASK_UNINTERRUPTIBLE. A process in an interruptible sleep state sleeps until a condition becomes true, such as generating a hardware interrupt, releasing system resources that the process is waiting for, or sending a signal can be a condition to wake up the process. The uninterruptible sleep state is similar to the interruptible sleep state, but it has one exception, that is, the process of transmitting the signal to this sleep state cannot change its state, that is, it does not respond to the awakening of the signal. Uninterruptible sleep is generally rarely used, but it is useful in certain situations, such as when the process must wait and cannot be interrupted until a particular event occurs.
In modern Linux operating systems, processes usually go to sleep by calling schedule (). The following code demonstrates
Shows how to put a running process to sleep.
Sleeping_task = current
Set_current_state (TASK_INTERRUPTIBLE)
Schedule ()
Func1 ()
/ * Rest of the code... , /
In the first statement, the program stores a process structure pointer sleeping_task,current, which is a macro that points to the executing
The process structure of the Set_current_state () changes the state of the process from execution state TASK_RUNNING to sleep state
TASK_INTERRUPTIBLE . If schedule () is scheduled by a process with a state of TASK_RUNNING, then schedule () will schedule another process to occupy the CPU. If schedule () is scheduled by a process with a status of TASK_INTERRUPTIBLE or TASK_UNINTERRUPTIBLE, an additional step will be performed: the currently executing process is removed from the run queue before another process is scheduled, which causes the running process to fall asleep because it is no longer in the run queue.
We can use the following function to wake up the process that just went to sleep.
Wake_up_process (sleeping_task)
After calling wake_up_process (), the state of the sleep process is set to TASK_RUNNING, and the scheduler
Will add it to the running queue. Of course, this process will not really be up and running until the next time it is scheduled by the scheduler.
Invalid wake-up
In almost all cases, the process will go to sleep after checking certain conditions and finding that the conditions are not met. But sometimes
The process begins to sleep after determining that the condition is true, and if so, the process will sleep indefinitely, which is the so-called invalid wake-up problem. In the operating system, when multiple processes attempt to process the shared data, and the final result depends on the order in which the processes are running, the competition condition will occur, which is a typical problem in the operating system. Invalid awakening is precisely caused by competitive conditions.
Imagine that there are two processes An and BJA working on a linked list. It needs to check whether the linked list is empty, and if not, align the chain.
The data in the table performs some operations, and the B process is also adding nodes to the linked list. When the linked list is empty, process A goes to sleep because there is no data to manipulate. When process B adds a node to the list, it wakes up process A. The code is as follows:
A process:
1 spin_lock (& list_lock)
2 if (list_empty (& list_head)) {
3 spin_unlock (& list_lock)
4 set_current_state (TASK_INTERRUPTIBLE)
5 schedule ()
6 spin_lock (& list_lock)
7}
eight
9 / * Rest of the code... , /
10 spin_unlock (& list_lock)
B process:
100 spin_lock (& list_lock)
List_add_tail (& list_head, new_node)
102 spin_unlock (& list_lock)
103 wake_up_process (processa_task)
There will be a problem if process B is scheduled by another processor when process An executes after line 3 and before line 4.
Put it into operation. During this time slice, process B has executed all its instructions, so it tries to wake up process A, which has not yet gone to sleep, so the wake-up operation is invalid. After that, the A process continues to execute, mistakenly thinking that the linked list is still empty at this time, so it sets its state to TASK_INTERRUPTIBLE and calls schedule () to sleep. Due to missing the wake-up of process B, it will sleep indefinitely, which is an invalid wake-up problem, because process A still sleeps even if there is data to process in the linked list.
Avoid invalid wake-up
How to avoid the problem of invalid wake-up? We find that invalid awakening mainly occurs after checking the condition and the process state is set to sleep.
Before the state, the wake_up_process () of process B provided an opportunity to set the state of process A to TASK_RUNNING, but at this time the state of process A was still TASK_RUNNING, so the efforts of wake_up_process () to change the state of process A from sleep to running did not play the expected role. To solve this problem, we must use a guarantee mechanism to make it an indivisible step to judge that the linked list is empty and set the process state to sleep state, that is, we must eliminate the root cause of the competitive bar, so that the wake_up_process () that appears after that can play the role of waking up the process in which the state is sleep.
Once you have found the reason, redesign the code structure of the A process to avoid the invalid wake-up problem in the above example.
A process:
1 set_current_state (TASK_INTERRUPTIBLE)
2 spin_lock (& list_lock)
3 if (list_empty (& list_head)) {
4 spin_unlock (& list_lock)
5 schedule ()
6 spin_lock (& list_lock)
7}
8 set_current_state (TASK_RUNNING)
nine
10 / * Rest of the code... , /
11 spin_unlock (& list_lock)
As you can see, this code sets the current execution process state to TASK_INTERRUPTIBLE before testing the condition, and sets itself to TASK_RUNNING state if the linked list is not empty. In this way, if process B checks the process A process
If wake_up_process () is called after the linked list is empty, then the state of the A process will automatically be changed from the original TASK_INTERRUPTIBLE
It becomes TASK_RUNNING, and even if the process calls schedule () again, it will not be removed from the runtime queue because it is now in the state of TASK_RUNNING, so it will not mistakenly go to sleep, and of course the invalid wake-up problem will be avoided.
An example of the Linux kernel
In the Linux operating system, the stability of the kernel is very important, in order to avoid invalid wake-up problems in the Linux operating system kernel.
The Linux kernel should use operations similar to the following when a process is required to sleep:
/ *'Q' is the waiting queue where we want to sleep * /
DECLARE_WAITQUEUE (wait,current)
Add_wait_queue (Q, & wait)
Set_current_state (TASK_INTERRUPTIBLE)
/ * or TASK_INTERRUPTIBLE * /
While (! condition) / * 'condition' is a condition for waiting * /
Schedule ()
Set_current_state (TASK_RUNNING)
Remove_wait_queue (Q, & wait)
The above action allows the process to safely add itself to a waiting queue for sleep through the following series of steps: first adjust the
Create an item in the waiting queue with DECLARE_WAITQUEUE (), then call add_wait_queue () to add yourself to the waiting queue and set the state of the process to TASK_INTERRUPTIBLE or TASK_INTERRUPTIBLE. Then loop to see if the condition is true: if so, there is no need to sleep, and if the condition is not true, call schedule (). When the conditions for the process check are met, the process sets itself to TASK_RUNNING and calls remove_wait_queue () to move itself out of the waiting queue.
As you can see from above, the kernel code maintainer of Linux also sets the state of the process to sleep before the process checks the condition.
Then cycle through the conditions. If the conditions are reached before the process starts sleeping, the loop exits and sets its state to ready with set_current_state (), which also ensures that the process does not have the wrong tendency to sleep and certainly does not cause invalid wake-up problems.
Let's use an example in the linux kernel to see how the Linux kernel avoids invalid sleep. This code is from the Linux2.6 kernel (linux-2.6.11/kernel/sched.c: 4254):
4253 / * Wait for kthread_stop * /
4254 set_current_state (TASK_INTERRUPTIBLE)
4255 while (! kthread_should_stop ()) {
4256 schedule ()
4257 set_current_state (TASK_INTERRUPTIBLE)
4258}
4259 _ _ set_current_state (TASK_RUNNING)
4260 return 0
The above code belongs to the migration service thread migration_thread, which constantly checks kthread_should_stop ()
It can't exit the loop until kthread_should_stop () returns 1, which means that the process will sleep as long as kthread_should_stop () returns 0. As we can see from the code, checking kthread_should_stop () does not start until the state of the process is set to TASK_INTERRUPTIBLE. Therefore, if another process tries to wake it up after the conditional check but before schedule (), the wake-up operation for that process will not fail.
After reading this, the article "what are the sleep and awakening methods of the Linux process" has been introduced. If you want to master the knowledge of this article, you still need to practice and use it yourself to understand it. If you want to know more about related articles, welcome to follow the industry information channel.
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.