Chapter III Process Management
3.1 Process
Process: A program in the execution period
A thread is an object in a process activity; the kernel dispatches a thread rather than a process, and in a Linux system, it does not differentiate between threads and processes.
In modern operating systems, processes provide two virtual mechanisms: virtual memory and virtual memory.
The process begins to survive at the time it was created, which is usually the result of calling the fork system. The system call creates a completely new process by copying an existing process. The fork system call returns two times from the kernel, one time to the parent process, and another to the newly generated child process.
Typically, a new process is created to execute the new program immediately, and then call the EXEC () function to create a new address space and load the new program into it, and in the modern Linux kernel, the fork () is actually implemented by the clone () system call.
The final program exits execution via the exit () system call, which ends the process and frees the resources it consumes.
3.2 Process descriptor and task structure
Process Descriptor: The process list is stored in a doubly linked list (Task list), which is the structure of the task_struct that is the process descriptor. The type is defined in <linux/sched.h>. The data contained in the process descriptor can fully describe an executing program:
- It opens the file
- The address space of the process
- Suspended signal
- Status of the process
- Other more information
3.2.1 Assigning process descriptors
Linux allocates TASK_ struct structure through slab, in order to achieve object reuse and cache coloring, so as to avoid resource consumption caused by dynamic allocation and release of resources.
The THREAD_INFO structure of each task is allocated at the end of its kernel stack, and the task field in the structure holds a pointer to the actual task_struct of the job.
3.2.2 Process Descriptor Storage
The kernel uses a unique process flag value fire PID to identify each process, the PID default maximum value is 32768, when needed can be modified/proc/sys/kernel/pid_max to increase the upper limit
Most of the code in the kernel that processes the processing process is done through the task_ struct, so you need to find the process descriptor for the currently running process through the current macro
In the X86 system, current blocks the 13 significant bits of the stack pointer, which is used to calculate the offset of the Thread_ info.
3.2.3 Process Status
The process must be in one of five states at any time.
- Task_running run-the process is executable
- Task_interrupt can be interrupted--the process is sleeping
- Task_uninterrupt Non-disruptive
- Task_traced processes that are tracked by other processes
- task_stopped Process stops running
3.2.4 Setting the current process state
Call the set_ task_ State (task,state) function to set the process to the specified status
3.2.5 Process Context
Executable code is an important part of the process, which is loaded from an EXE file into the address space of the process.
3.2.6 Process Family Tree
All processes are descendants of the init process with PID 1.
All processes that have the same parent process are called brothers, the relationship between the processes is stored in the process descriptor, each task_struct contains a pointer to its parent process, and a list of child processes, and for the current process, the process descriptor of the parent process can be obtained from the following code:
struct Task_struct *my_parent = current->parent;
For a given process, get the next process in the list:
List_ entry (task->tasks.prev,struct task_struct,tasks)
3.3 Process Creation
How the UNIX system processes are created:
Fork () Creates a child process by copying the current process
EXEC () is responsible for reading the executable file and loading it into the address space to start running
3.3.1 Write-time copy
Linux fork () uses write-time copies to postpone or even dispense copies. The kernel does not replicate the entire address space when it creates a new process, but rather allows the parent process and child processes to share the same copy, until the child process/parent process needs to write it.
The actual cost of fork is simply to copy the page table of the parent process and create a unique process descriptor for the child process
3.3.2 Fork ()
Linux implements fork via clone system call
The fork (), vfork (), and _clone () library functions call Clone () according to their required parameter flags, and then the clone goes to invoke the Do_fork ()
Define Do_ fork () in <kernel/fork.c> to complete most of the work in the creation, it calls the Copy_process function, and then lets the process start running
The work done by the copy_process () function:
3.3.3 Vfork ()
Vfork () Does not copy the page table entries of the parent process. The child process runs as a separate thread of the parent process in its address space, and the parent process is blocked until the child process exits or executes exec ().
The implementation of the Vfork () system call is done by passing a special flag to the clone () system call:
3.4 Implementation of threads in Linux
The threading mechanism provides a set of threads running in shared memory address space within the same program, which can also share open files and other resources, and the threading mechanism supports concurrent programming techniques, and it also guarantees true parallel processing on multiprocessor systems.
In a Linux system, a thread is only considered a process that shares certain resources with other processes. Each thread has its own task_struct.
3.4.1 Creating Threads
Threads are created similar to normal processes, except that you need to pass some parameter flags to indicate shared resources when you call Clone ().
The parameter flags passed to clone () determine how the new creation process behaves and what kind of resources are shared between the parent and child processes
3.4.2 Kernel Thread
Kernel threads do not have a separate address space, only run in kernel space, do not switch to user space, can be scheduled, can also be preempted.
It can only be created through other kernel threads, and the kernel derives all kernel threads through the Kthread kernel process
The newly created thread is in a non-operational state until Wake_ Up_process () explicitly wakes it
3.5 Process End
Work of Do_exit ():
3.5.1 Deleting a process descriptor
This task is performed separately from cleanup work, because the system can still get its information after the process is terminated
Implementation of Process descriptor deletion via Release_task ()
3.5.2 The dilemma caused by the orphan process
The parent process exits before the process, leaving behind the child process, the orphan process
Find a new parent process for the orphan process within the current thread group, or directly with Init as its parent process
3.6 Summary
Processes and threads, how Linux stores and represents processes, how to create processes, how the parent process collects descendant information, and how the process ends.
Linux kernel Analysis Sixth week reading notes