A brief analysis of the sleep and wake-up of Linux process

Source: Internet
Author: User

COPY FROM:HTTP://WWW.2CTO.COM/OS/201204/127771.HTML1 Linux process sleep and wake up in Linux, processes that wait only for CPU time are called ready processes, and they are placed in a running queue, 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 processes need to wait until a particular event occurs, such as device initialization, completion of I/O operations, or timer-to-time.  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 www.2cto.com Linux:
One is the interruptible sleep state, its status flag bit task_interruptible, the other is the non-interruptible sleep state, its status flag bit is task_uninterruptible. A process with an interrupted sleep state sleeps until a condition becomes true, such as creating a hardware interrupt, releasing the system resources that the process is waiting for, or passing a signal that can be the condition of the wake 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, the process is typically called schedule () to sleep, and the following code shows how to get the 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 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);  www.2cto.com   after calling Wake_up_process (), the state of the sleep process is set to task_running, and the scheduler will add it to the run queue. Of course, this process can only be really put into operation the next time the scheduler is dispatched.  2 invalid wake-up fewIn all cases, the process will go to sleep after examining 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: 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}89/* Rest of the code ... */10 spin_unlock (&list_lock);
B Process: Spin_lock (&list_lock), 101 list_add_tail (&list_head, New_node); 102 Spin_unlock (&list_lock); Www.2cto.com 103 wake_up_process (processa_task); there is a problem here, if a process executes to the 4th line after the 3rd line, the B process is scheduled to run by another processor. 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. 3 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. Once you have found the reason, redesign 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); 910/* Rest of the code ... */11 spin_unlock (&list_lock); As you can see, it turns the current execution process state to task_interruptible before testing the condition. And when the linked list is not empty, it also resets itself to the task_running state. In 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 change from the original task_interruptible to task_running, even if the process calls the schedule (), because it is now task_running, it will still not be removed from the run queue, so it will not go to sleep incorrectly, and of course avoids the problem of invalid wakeup.  4 Linux Kernel example in the Linux operating system, the kernel stability is critical, in order to avoid the Linux operating system kernel in the failure to wake the problem, the Linux kernel should need to sleep in the process should use a similar operation:/* ' Q ' is the waiting queue */declare_waitqueue (wait,current) We want to sleep, Add_wait_queue (q, &wait); Set_current_state (task_ interruptible);/* or task_interruptible */while (!condition)/* ' condition ' is the waiting Condition */schedule ();  www.2cto.com  set_current_state (task_running); Remove_wait_queue (q, &wait); The above operation, Enables the process to safely add itself to a wait queue for sleep by using the following sequence of steps: First call Declare_waitqueue () to create an item waiting for the queue.Then call Add_wait_queue () to add itself 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, and then loops through the condition. 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 take a look at examples from 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;  www.2cto.com   The above code belongs to the Migration Service thread Migration_thread, which constantly checks kthread_should_stop () until Kthread_should_stop () Returns 1 it can exit the loop, meaning 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 through the above discussion, it can be found that the key to avoiding invalidation of processes in Linux is to set the status of the process to task_interruptible or task_uninterruptible before the process checks the conditions. 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. 1 sleep and wake-up of Linux processes in Linux, processes that wait only for CPU time are called ready processes, they are placed in a running 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 dispatchfunction, which can be actively 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 processes need to wait until a particular event occurs, such as device initialization, completion of I/O operations, or timer-to-time. 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  www.2cto.com  linux:
One is the interruptible sleep state, its status flag bit task_interruptible, the other is the non-interruptible sleep state, its status flag bit is task_uninterruptible. A process with an interrupted sleep state sleeps until a condition becomes true, such as creating a hardware interrupt, releasing the system resources that the process is waiting for, or passing a signal that can be the condition of the wake 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, the process is typically called schedule () to sleep, and the following code shows how to get the 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 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);  www.2cto.com   after calling Wake_up_process (), the state of the sleep process is set to task_running, and the scheduler will add it to the run queue. Of course, this process can only be really put into operation the next time the scheduler is dispatched.  2 invalid wake-up fewIn all cases, the process will go to sleep after examining 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: 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}89/* Rest of the code ... */10 spin_unlock (&list_lock);
B Process: Spin_lock (&list_lock), 101 list_add_tail (&list_head, New_node); 102 Spin_unlock (&list_lock); Www.2cto.com 103 wake_up_process (processa_task); there is a problem here, if a process executes to the 4th line after the 3rd line, the B process is scheduled to run by another processor. 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. 3 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. Once you have found the reason, redesign 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); 910/* Rest of the code ... */11 spin_unlock (&list_lock); As you can see, it turns the current execution process state to task_interruptible before testing the condition. And when the linked list is not empty, it also resets itself to the task_running state. In 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 change from the original task_interruptible to task_running, even if the process calls the schedule (), because it is now task_running, it will still not be removed from the run queue, so it will not go to sleep incorrectly, and of course avoids the problem of invalid wakeup.  4 Linux Kernel example in the Linux operating system, the kernel stability is critical, in order to avoid the Linux operating system kernel in the failure to wake the problem, the Linux kernel should need to sleep in the process should use a similar operation:/* ' Q ' is the waiting queue */declare_waitqueue (wait,current) We want to sleep, Add_wait_queue (q, &wait); Set_current_state (task_ interruptible);/* or task_interruptible */while (!condition)/* ' condition ' is the waiting Condition */schedule ();  www.2cto.com  set_current_state (task_running); Remove_wait_queue (q, &wait); The above operation, Enables the process to safely add itself to a wait queue for sleep by using the following sequence of steps: First call Declare_waitqueue () to create an item waiting for the queue.Then call Add_wait_queue () to add itself 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, and then loops through the condition. 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 take a look at examples from the Linux kernel to see how the Linux kernel avoids invalid sleep, this code is from Linux2.6 's 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; Www.2cto.com the above code belongs to the Migration Service thread Migration_thread, which constantly checks kthread_should_stop () until Kthread_should_stop () returns 1 before it can exit the loop, This means that as long as Kthread_should_stop () returns 0 the process will sleep. 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 through the above discussion, it can be found that the key to avoid invalidation of process in Linux is to set the status of the process to task_interruptible or task_uninterruptible before the process checks the condition. 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.

A brief analysis of the sleep and wake-up of Linux process

Related Article

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.