Chapter III, Process Management
3.1 Process
1. The process is a procedure that is in the implementation phase, but the process is not confined to a single executable code
2. Execution Thread:
A thread, which is an object that is active in a process. Each thread has a separate program counter, a process stack, and a set of process counters.
3. In modern operating systems, processes provide two virtual mechanisms: virtual processors and virtual memory.
4. The procedure itself is not a process, and the process is a general term for the procedures and related resources in the implementation period.
5.fork (): Causes the process to survive when it is created;
Exec (): Creates a new address space and loads the new program into it;
Exit (): Exit execution.
3.2 Process descriptor and task structure
1. Process Descriptor:
The kernel stores the list of processes in a two-way circular chain table called the task queue. Each item in the list is a structure of type task_struct, called the process descriptor.
2. The data contained in the process descriptor can fully describe an executing program: The file It opens, the address space of the process, the pending signal, the status of the process, and more information.
3.2.1 Assigning process descriptors
Linux allocates task_struct structures through the slab allocator.
Since the task_struct is now dynamically generated with the slab allocator, a new struct struct thread_info is simply created at the bottom or top of the stack.
The THREAD_INFO structure of each task is allocated at the end of its kernel stack. A task field in a structure holds a pointer to the actual task_struct of the task.
3.2.2 Process Descriptor Storage
The kernel identifies each process through a unique process identity value or PID.
In the kernel, access tasks usually need to get pointers to their task_struct.
3.2.3 Process Status
(five status of process)
Task_running (running)
Task_interruptible (can be interrupted)
Task_uninterruptible (non-disruptive)
_task_traced
_task_stopped (STOP)
3.2.4 Setting the current process state
Using the Set_task_state (task,state) function
3.2.5 Process Context
Executable code is an important part of the process. The code is executed from an executable file loaded into the address space of the process. The general program executes in user space. When a
When a program executes a system call or triggers an exception, it falls into kernel space, where we call the kernel "execute on behalf of the process" and in the context of the process.
3.2.6 Process Family Tree
Inheritance relationship
3.3 Process Creation
UNIX uses a different approach, which breaks down the steps of other operating systems into two separate functions to execute: fork () and exec ();
Fork () Creates a child process by copying the current process.
The Exec () function is responsible for reading the executable file and loading it into the address space to start running.
3.3.1 Write-time copy
The data is copied only when there is a need to write, so that each process has its own copy.
3.3.2 Fork ()
Linux implements Fork () via Clone () system call
Do_fork completes most of the work in the creation, which calls the Copy_process () function and then lets the process begin running.
3.3.3 Vfork ()
The vfork () system call and the fork () function are the same except for page table entries that do not copy the parent process.
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
3.4.1 Creating Threads
Creating a thread is similar to creating a normal process, except that you need to pass some parameter flags when invoking clone () to indicate which resources need to be shared:
Clone (CLONE_VM | Clone_fs | Clone_files | clone_sighand,0);
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
Perform some operations in the background
3.5 Process End
3.5.1 Deleting a process descriptor
Removal of cleanup work and process descriptors required at the end of the process is performed separately. After the parent process obtains information about the child process that has been terminated, or notifies the kernel that it is not concerned
After that information, the TASK_STRUCT structure of the child process can be released.
3.5.2 The dilemma caused by the orphan process
If the parent process exits before the child process, there must be a mechanism to ensure that the child process can find a new parent process, otherwise these orphaned processes will always be on exit
Zombie state, which consumes memory in vain.
"Linux kernel Design and implementation" Chapter 3rd book Finishing