Sleep and wake-up of Linux processes

Source: Internet
Author: User


First, sleep and wake-up of Linux processes

In Linux, wait only for the CPUThe process of time is called the ready process, they are placed in a run queue, and the status flag bit for a ready process is task_running. Once a running process time slice is exhausted, the Linux kernel Scheduler will deprive the process of control of the CPU and choose a suitable process from the running queue to run.

Of course, a process can also voluntarily release control of the CPU. The function schedule () is a dispatch function that can be invoked by a process to schedule other processes to occupy the CPU. Once the process that actively abandons the CPU is re-dispatched to occupy the CPU, it executes from the location where it was last stopped, that is, it will start at the next line of code called Schedule ().

Sometimes a process needs to wait until a particular event occurs, such as device initialization complete, I/O operation is complete, orTimer to the time and so on. In this case, the process must be moved out of the running queue and joined to a wait queue, when the process goes to sleep.

There are two kinds of process sleep states in Linux:

One is an interruptible sleep state with its status flag bit task_interruptible
The other is a non-interruptible sleep state with a status flag of task_uninterruptible

A process with an interrupted sleep state sleeps until a condition becomes true, such as creating a hardware interrupts, the system that the release process is waiting for resources or passing a signal can be the condition of the wakeup process. The non-disruptive sleep state is similar to an interruptible sleep state, but it has one exception: the process of transmitting a signal to this sleep state cannot change its state, meaning it does not respond to the wake of the signal. Non-disruptive sleep states are generally less useful, but in some specific situations this state can be helpful, for example: a process must wait and not be interrupted until a particular event occurs.

    in modern Linux operating systems, processes usually go to sleep using a method called Schedule (), and the following code shows how to put a running process into a sleep state.

Sleeping_task = current;
Set_current_state (task_interruptible);
Schedule ();
Func1 ();
/* Rest of the code ... */

    in the first statement, program stores a copy of the process structure pointer sleeping_task, Current is a macro that points to the process structure that is being executed. Set_current_state () Changes the state of the process from the execution state task_running to the sleep state task_interruptible. If schedule () is dispatched by a process with a state of task_running, then schedule () will dispatch another process to occupy the CPU; if schedule () is a state of task_interruptible or Task_ Uninterruptible process scheduling, then there is an additional step that will be executed: the currently executing process will be removed from the run queue before another process is dispatched, which will cause the running process to go to sleep because it is no longer in the running queue.

    We can use this function to wake up the process that went to sleep just now.

wake_up_process (sleeping_task);

after Wake_up_process () is called, the state of the sleep process is set to task_running, and the scheduler adds it to the run queue. Of course, this process can only be really put into operation the next time the scheduler is dispatched.


Second. Invalid Wakeup

In almost all cases, the process will go to sleep after checking for certain conditions and discovering that the condition is not satisfied. But sometimes the process will start to sleep when the condition is true, and if so the process will hibernate indefinitely, this is called the invalid wake-up problem. In the operating system, when multiple processes attempt to do some processing of the shared data, and the final result depends on the order in which the process is run, a race condition occurs, which is a typical problem in the operating system, which is caused by an invalid wake-up due to a competitive condition.

Imagine that two processes a and b,a processes are working on a linked list, it needs to check if the list is empty, and if not empty, some operations on the data in the list, and the B process is also adding nodes to the list. When the list is empty, because of countless data can be manipulated, then a process goes to sleep, when the B process adds a node to the list, it wakes up a process, its code is as follows:

A process:
1Spin_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}
8
9/* Rest of the code ... * *
Ten Spin_unlock (&list_lock);

B Process:
Spin_lock (&list_lock);
101 List_add_tail (&list_head, New_node);
102 Spin_unlock (&list_lock);
103 wake_up_process (Processa_task);

A problem arises if the B process is scheduled to run by another processor when the a process executes until the 4th line after line 3rd. In this time slice, the B process executes all of its instructions, so it tries to wake up the a process, and the a process does not go to sleep, so the wake operation is not valid. After that, the a process continues to execute, and it mistakenly considers the list to be empty at this time, and then sets its state to task_interruptible and then calls schedule () into sleep. Because Miss B process wakes up, it will sleep indefinitely, this is the invalid wake problem, because even if there is data in the list to be processed, a process is still sleep.


Third. Avoid invalid wakeup

How do you avoid invalid wake-up problems? We found that the invalid wakeup occurred mainly after the check condition and the process state was set to sleep before the wake_up_process () of the B process provided an opportunity to set the a process state to task_running, but this time the status of a process is still task_ RUNNING, so the effort of wake_up_process () to turn a process state from sleep to running state has not worked as expected. To solve this problem, it is necessary to use a safeguard mechanism to make it an inseparable step to judge the list to be empty and to set the state of the process to sleep, that is, the root cause of the competition condition must be eliminated so that the wake_up_process () Can wake up state is the process of sleep state of action.
After finding the cause, re-Design the code structure of the a process to avoid the invalid wake-up problem in the example above.
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);
9
Ten/* 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 resets itself to the task_running state if the linked list is not empty. This way if the B process checks the list to be empty after the a process process has checked the wake_up_process (), then the status of a process will automatically be task_interruptible by the original
becomes task_running, and after that, even if the process calls schedule (), because it is now task_running, it is still not removed from the run queue, so it does not go wrong into sleep, and of course avoids the problem of invalid wakeup.

Fourth, examples of Linux kernels
In the Linux operating system, the stability of the kernel is critical, in order to avoid invalid wake-up problems in the Linux operating system kernel,
The Linux kernel should use a procedure similar to the following when it needs to process 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 waiting condition */
Schedule ();
Set_current_state (task_running);
Remove_wait_queue (q, &wait);
The above action allows the process to safely add itself to a wait queue for sleep in the following sequence of steps: First tune
Create a queue-waiting item with Declare_waitqueue (), and then call Add_wait_queue () to add yourself to the wait queue and set the status of the process to task_interruptible or task_ Interruptible. Then the loop checks whether 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 then sets itself to task_running and calls Remove_wait_queue () to move itself out of the waiting queue.
As can be seen from the above, the kernel code maintainer of Linux also sets the state of the process to sleep before the process checks the condition.
The check condition is then cycled. If the condition is reached before the process starts to sleep, the loop exits and sets its state to ready with set_current_state (), which also guarantees that the process will not have the wrong tendency to go to sleep and, of course, will not cause an invalid wakeup problem.
Let's use the followingExamples from the Linux kernel look at how the Linux kernel avoids invalid sleep, which is derived 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 for kthread_should_stop (),
Until Kthread_should_stop () returns 1 it can exit the loop, which means that the process will sleep as long as Kthread_should_stop () returns 0. As we can see from the code, the check Kthread_should_stop () does not begin executing until the process state is set to task_interruptible. Therefore, if another process tries to wake it after the condition check but before schedule (), the wake-up operation of the process is not invalidated.

Summary
From the discussion above, it can be found that the key to avoiding invalid wake-up processes in Linux is to process the
The state is set to Task_interruptible or task_uninterruptible, and if the checked condition is met, it should
Reset its state to task_running. This avoids an invalid wake-up problem, regardless of whether the process waits for the condition to be satisfied, and the process does not go to sleep incorrectly because it is moved out of the ready queue.


Sleep and wake-up of Linux processes


Alibaba Cloud Hot Products

Elastic Compute Service (ECS) Dedicated Host (DDH) ApsaraDB RDS for MySQL (RDS) ApsaraDB for PolarDB(PolarDB) AnalyticDB for PostgreSQL (ADB for PG)
AnalyticDB for MySQL(ADB for MySQL) Data Transmission Service (DTS) Server Load Balancer (SLB) Global Accelerator (GA) Cloud Enterprise Network (CEN)
Object Storage Service (OSS) Content Delivery Network (CDN) Short Message Service (SMS) Container Service for Kubernetes (ACK) Data Lake Analytics (DLA)

ApsaraDB for Redis (Redis)

ApsaraDB for MongoDB (MongoDB) NAT Gateway VPN Gateway Cloud Firewall
Anti-DDoS Web Application Firewall (WAF) Log Service DataWorks MaxCompute
Elastic MapReduce (EMR) Elasticsearch

Alibaba Cloud Free Trail

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.