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 > Servers >
Share
Shulou(Shulou.com)06/01 Report--
In this issue, the editor will bring you about how to set sleep and wake up in Linux. The article is rich in content and analyzes and narrates it from a professional point of view. I hope you can get something after reading this article.
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 * statements, 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 will begin to sleep after determining that the condition is true, if so, the process will go dormant for a period of time, which is the so-called invalid wake-up problem. In the operating system, when multiple processes attempt to do some kind of processing of shared data, and the result of * depends on the order in which the processes run, a race condition occurs, which is a typical problem in the operating system. Invalid wake-up is precisely caused by competition 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:
Spin_lock (& list_lock); if (list_empty (& list_head)) {spin_unlock (& list_lock); set_current_state (TASK_INTERRUPTIBLE); schedule (); spin_lock (& list_lock);} / * Rest of the code... * / spin_unlock (& list_lock)
B process:
Spin_lock (& list_lock); list_add_tail (& list_head, new_node); spin_unlock (& list_lock); 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 for a period of time, which is an invalid wake-up problem, because process A still sleeps even if there is data to be processed 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:
Set_current_state (TASK_INTERRUPTIBLE); spin_lock (& list_lock); if (list_empty (& list_head)) {spin_unlock (& list_lock); schedule (); spin_lock (& list_lock);} set_current_state (TASK_RUNNING); / * Rest of the code. * / 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 the 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):
/ * Wait for kthread_stop * / set_current_state (TASK_INTERRUPTIBLE); while (! kthread_should_stop ()) {schedule (); set_current_state (TASK_INTERRUPTIBLE);} _ set_current_state (TASK_RUNNING); 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.
This is how the process in Linux is set to sleep and wake up. If you happen to have similar doubts, you might as well refer to the above analysis to understand. If you want to know more about it, you are 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.