Analysis of various Linux Processes

Source: Internet
Author: User
Tags high cpu usage

Linux Process status analysis

As we all know, the current time-sharing operating system can run multiple programs on a single CPU, making these programs seem to be running at the same time. Linux is such an operating system.
In Linux, each running program instance corresponds to one or more processes. The Linux kernel needs to manage these processes so that they can run simultaneously in the system. The Linux kernel manages processes in two aspects: Process status management and process scheduling. This article mainly introduces process status management. For details about process scheduling, see Linux Process Scheduling analysis.

Process status

In Linux, we can use the ps command to view the processes in the system and their statuses:

R (task_running), the executable status.

Only processes in this status can run on the CPU. Multiple processes may be executable at the same time. The task_struct structure of these processes (Process Control Block) put into the executable queue of the corresponding CPU (a process can only appear in the executable queue of one CPU ). The task of the Process scheduler is to select a process from the executable queue of each CPU to run on this CPU.
As long as the executable queue is not empty, the CPU corresponding to it cannot be lazy and a process must be executed. Generally, the CPU is "busy ". Correspondingly, the CPU "idle" means that the corresponding executable queue is empty, so that the CPU has nothing to do.
Someone asked why the dead loop program causes high CPU usage? Because the endless loop program is basically in the task_running State (the process is in an executable Queue ). Unless in some extreme situations (such as a serious shortage of system memory, some pages to be used by the process are swapped out, and the pages cannot be allocated to memory when they need to be swapped in ......), Otherwise, the process will not sleep. Therefore, the CPU executable queue is always not empty (at least such a process exists), and the CPU will not be "idle ".

Many operating system textbooks define the processes being executed on the CPU as running, while the processes that can be executed but have not been scheduled as ready, these two statuses are in the task_running state in Linux.

S (task_interruptible), an interrupted sleep state.

A process in this status is suspended because it waits for the occurrence of a certain event (such as waiting for socket connection or semaphore. The task_struct structure of these processes is put into the wait queue of corresponding events. When these events occur (triggered by external interruptions or by other processes), one or more processes in the corresponding waiting queue will be awakened.

The ps command shows that the vast majority of processes in the process list are in the task_interruptible state (unless the machine has a high load ). After all, there are one or two CPUs and hundreds of processes. if not most processes are sleeping, how can the CPU respond.

D (task_uninterruptible.

Like task_interruptible, the process is in sleep state, but the process cannot be interrupted at the moment. Non-disruptive means that the CPU does not respond to external hardware interruptions, but that the process does not respond to asynchronous signals.
In most cases, when a process is sleeping, it should always be able to respond to asynchronous signals. Otherwise, you will be surprised to find that kill-9 is not killing a sleeping process! As a result, we also understand why the ps command shows almost no task_uninterruptible status for the process, but always task_interruptible status.

The significance of the task_uninterruptible status lies in that some kernel processing processes cannot be interrupted. If an asynchronous signal is returned, a program is inserted into the execution process to process the asynchronous signal. (The inserted process may only exist in the kernel state, it may also extend to the user State), so the original process is interrupted (see Linux asynchronous signal handle analysis).
When a process operates on certain hardware (for example, a process calls the read system call to read a device file, and the read system call finally executes the code of the corresponding device driver, and interact with the corresponding physical device), you may need to use the task_uninterruptible status to protect the process, so as to prevent the process of interaction between the Process and the device from being interrupted, causing the device to fall into an uncontrollable state. (For example, a read System Call triggers the DMA of the memory from the disk to the user space. If the process exits due to the response signal during the DMA process, the memory accessed by DMA may be released .) In this case, the status of task_uninterruptible is always very short, and it is basically impossible to capture it through the ps command.

In Linux, task_uninterruptible is easily captured. After the vfork system is called, the parent process enters the task_uninterruptible State until the child process calls exit or exec (see magic vfork).
The following code can be used to obtain a process in the task_uninterruptible state:
# Include <unistd. h>
Void main (){
If (! Vfork () sleep (100 );
}
Compile and run the program. PS:
Kouu @ kouu-one :~ /Test $ PS-ax | grep A \. Out
4371 pts/0 d +./A. Out
4372 pts/0 S +./A. Out
4374 pts/1 S + grep A. Out
Then we can test the power of the task_uninterruptible status. Whether killed or killed-9, the parent process in the task_uninterruptible status still stands.

T (task_stopped or task_traced), paused or tracked.

When a sigstop signal is sent to a process, it enters the task_stopped status because it responds to the signal (unless the process itself is in the task_uninterruptible status and does not respond to the signal ). (The sigstop signal is the same as the sigkill signal, which is very mandatory. User processes are not allowed to reset the corresponding signal processing functions through system calls of the signal series .)
Send a sigcont signal to the process to restore it from the task_stopped status to the task_running status.

When a process is being tracked, it is in the special state of task_traced. "Being tracked" means that the process is paused and is waiting for the process to be tracked to operate on it. For example, in GDB, a breakpoint is placed on the tracked process, and the process is in the task_traced state when it stops at the breakpoint. At other times, the tracked process is still in the aforementioned state.

For the process itself, the status of task_stopped is similar to that of task_traced, indicating that the process is paused.
In the task_traced state, the protection layer is added to the task_stopped state. A process in the task_traced state cannot be awakened when it responds to the sigcont signal. The debugged process can be restored to the task_running State only when the debugging process performs operations such as ptrace_cont and ptrace_detach through the ptrace System Call (the operation is specified through the parameters called by the ptrace system), or when the debugging process exits.

Z (task_dead-exit_zombie), exit, and the process becomes a zombie process.

The process is in the task_dead status when it exits.

During this exit process, all resources occupied by the process will be reclaimed, except for the task_struct structure (and a few resources. As a result, the process has only such an empty shell as task_struct, so it is called a zombie.
Task_struct is retained because the process exit code and some statistics are saved in task_struct. The parent process may be concerned with this information. For example, in shell, $? The variable stores the exit code of the Last Exit foreground process, which is often used as the judgment condition of the IF statement.
Of course, the kernel can also save this information elsewhere and release the task_struct structure to save some space. However, it is more convenient to use the task_struct structure, because the search relationship from PID to task_struct has been established in the kernel, as well as the parent-child relationship between processes. To release task_struct, you need to create a new data structure so that the parent process can find the exit information of its child process.

The parent process can wait for the exit of a child or child process and obtain its exit information through wait system calls (such as wait4 and waitid. Then the wait system calls will release the child process bodies (task_struct) by the way.
When a child process exits, the kernel sends a signal to its parent process to notify the parent process to "collect dead ". This signal is sigchld by default, but you can set this signal when creating a sub-process by calling the clone system.

The following code creates an exit_zombie process:
# Include <unistd. h>
Void main (){
If (Fork ())
While (1) sleep (100 );
}
Compile and run the program. PS:
Kouu @ kouu-one :~ /Test $ PS-ax | grep A \. Out
10410 pts/0 S +./A. Out
10411 pts/0 z + [A. Out] <defunct>
10413 pts/1 S + grep A. Out

As long as the parent process does not exit, the child process in this zombie state will always exist. So if the parent process exits, who will "collect" the child process "?
When a process exits, it will host all its sub-processes to other processes (making them sub-processes of other processes ). Who is hosting? It may be the next process (if any) in the process group where the process is located, or process 1. Therefore, every process and every moment has a parent process. Unless it is a process no. 1.

Process 1, a process whose PID is 1, also known as the INIT process.
After Linux is started, the first user-state process created is the INIT process. It has two missions:
1. Execute the system initialization script to create a series of processes (all of them are descendants of the INIT process );
2. Wait for the exit event of its child process in an endless loop and call the waitid system call to complete the "zombie" operation;
The INIT process will not be paused or killed (this is guaranteed by the kernel ). It is in the task_interruptible status while waiting for the sub-process to exit, while the "zombie" process is in the task_running status.

X (task_dead-exit_dead). The process is about to be destroyed.

The process may not keep its task_struct during exit. For example, this process is a process (process? Thread? See Linux thread analysis). Or the parent process explicitly ignores the sigchld signal by setting the handler of the sigchld signal to sig_ign. (This is POSIX, although the exit signal of the sub-process can be set to a signal other than sigchld .)
At this point, the process will be placed in the exit_dead exit state, which means that the next code will immediately release the process completely. Therefore, the exit_dead status is very short, and it is almost impossible to capture it through the ps command.

Initial Process status

Processes are created through fork system calls (fork, clone, and vfork). The kernel (or kernel module) can also create kernel processes through the kernel_thread function. The functions used to create sub-processes are essentially the same-copy the calling process to obtain the sub-process. (You can use option parameters to determine whether resources are shared or private .)
Now that the calling process is in the task_running state (otherwise, if it is not running, how can it be called ?), The sub-process is also in the task_running status by default.
In addition, the clone_stopped option is also accepted when the system calls clone and kernel function kernel_thread, so that the initial state of the sub-process is set to task_stopped.

Process status change

After a process is created, its status may change until the process exits. Although there are several process statuses, there are only two directions for Process status change-from task_running to non-task_running, or from non-task_running to task_running.
That is to say, if a process in the task_interruptible State sends a sigkill signal, the process will first be awakened (into the task_running State), and then exit (into the task_dead State) in response to the sigkill signal ). It does not exit directly from the task_interruptible status.

A process changes from a non-task_running state to a task_running state, which is implemented by other processes (or possibly interrupt the processing program) Performing the wake-up operation. Set the status of the wake-up process to task_running and add its task_struct structure to the executable queue of a CPU. The wake-up process will have the opportunity to be scheduled for execution.

The process changes from the task_running status to the non-task_running status, there are two ways:
1. The response signal enters the task_stoped or task_dead status;
2. Execute the system call to actively enter the task_interruptible status (such as nanosleep System Call), or task_dead status (such as exit system call); or because the resources required for executing the system call are not satisfied, the status changes to task_interruptible or task_uninterruptible (for example, the Select system call ).
Obviously, both cases can only happen when the process is being executed on the CPU.

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.