1. Process and thread
The process is in the execution periodProgramContains independent address space, multiple execution threads, and other resources.
A thread is an activity object in a process. Each thread has an independent program counter, a process stack, and a set of process registers.
The kernel scheduling object is a thread rather than a process. For Linux, threads are special processes.
Binary process Descriptor and Task Structure
The kernel uses a two-way cyclic linked list task queue to store processes, and the struct task_struct is used to describe all process information.
1. Process descriptor task_struct
Struct task_struct {} has a large struct of about KB. For more information, see:
2. Allocate process Descriptors
When a process is interrupted or the system calls are switched from the user State to the kernel state, the stack used by the process must also be switched from the user stack to the kernel stack.
Obtain thread_info at the end of the stack through the kernel stack to obtain the current process descriptor task_struct.
The thread_info structure of each process is allocated at the end of the kernel stack. In the structure, the task domain is the actual task_struct pointing to the task.
The kernel processing process operates through the process descriptor task_struct struct object. Therefore, the operating process must obtain the currently running process descriptor.
The task_struct address can be found through the address of thread_info; the offset address of thread_info is calculated differently in different architectures.
/* Linux-2.6.38.8/ARCH/ARM/include/ASM/current. h */ Static Inline Struct Task_struct * get_current ( Void ){ Return Current_thread_info ()-> Task ;} # Define Current (get_current ()) /* Linux-2.6.38.8/ARCH/ARM/include/ASM/thread_info.h */ Static Inline Struct Thread_info * current_thread_info (Void ){ // Stack pointer Register unsigned Long Sp asm ( " SP " ); Return ( Struct Thread_info *) (sp &~ (Thread_size- 1 ));}
3. Process status
Every process in the system must be in one of the five processes or be switched. The value of this field must also be one of the following five status signs:
Task_running(Run)-the process is executable; it is either in progress or waiting for execution in the running Queue (the running queue will be discussed in chapter 4th ).
This is the only possible state for a process to be executed in the user space. This state can also be applied to a process that is being executed in the kernel space.
Task_interruptible(Can be interrupted)-the process is sleeping (that is, it is blocked), waiting for fulfillment of certain conditions. Once these conditions are met,
The kernel sets the Process status to run. Processes in this status will also be awakened in advance and ready to run at any time because they receive signals.
Task_uninterruptible(Non-disruptive)-this status is the same as the status that can be interrupted, except that a signal is not awakened or ready for running.
This State usually occurs when the process has to wait without interference or when the wait event occurs soon. Because tasks in this status do not respond to signals,
Therefore, it is used less than the resumable status.
_ Task_traced-Processes tracked by other processes, for example, debugging programs through ptrace.
_ Task_stopped(STOP)-the process stops running. The process is neither running nor running. Generally, this status occurs when sigstop,
Sigtstp, sigttin, sigttou and other signals. In addition, any signal received during debugging will bring the process into this state.
Three-Process Creation
Fork: copy the current process to create a new process;
Exec: Read the executable file and load it into the address space to start running.
1 forkProcess
Process Creation is completed by calling the do_fork function. Many parameter flags are provided to indicate the method of Process Creation.
Long Do_fork (unsigned Long Clone_flags, unsigned Long Stack_start, Struct Pt_regs *Regs, unsigned Long Stack_size, Int _ User * Parent_tidptr, Int _ User * Child_tidptr ){ Struct Task_struct * P ;...... // Create Process P =Copy_process (clone_flags, stack_start, regs, stack_size, child_tidptr, null, trace );...... // Add processes to the running queue Wake_up_new_task (p );}
Copy_processIt creates sub-processes through the parent process and does not execute:
Task_struct * copy_process (unsigned Long Clone_flags, unsigned Long Stack_start, Struct Pt_regs *Regs, unsigned Long Stack_size, Int _ User * Child_tidptr, Struct PID * PID, Int Trace ){ Struct Task_struct * P; // Create process Kernel stack and process Descriptor P = Dup_task_struct (current ); // The obtained process is exactly the same as that of the parent process. initialize the newly created process. ...... Return P ;}
Dup_task_structCreate a sub-process Kernel stack and process descriptor Based on the parent process:
Static Struct Task_struct * dup_task_struct ( Struct Task_struct * Orig ){ Struct Task_struct * Tsk; Struct Thread_info * Ti; Int Node = Tsk_fork_get_node (orig ); // Create process descriptor object Tsk = Alloc_task_struct_node (node );
// Create process Kernel stack thread_info Ti =Alloc_thread_info_node (tsk, node ); // Make the sub-process descriptor consistent with the parent process Err = Arch_dup_task_struct (tsk, orig ); // Process descriptor stack points to thread_info Tsk -> Stack = Ti; // Make the thread_info content of the sub-process consistent with that of the parent process, but the task points to the sub-process task_struct. Setup_thread_stack (tsk, orig ); Return Tsk ;}
After the copy_process process is created, it is not executed. It is returned to do_fork, and the newly created process is added to the running queue for execution.
Implementation of four threads in Linux and kernel threads
The thread Mechanism provides a set of threads that share memory address space, files, and other resources in the same program. In the Linux kernel, all threads are implemented as processes.
The kernel does not provide SchedulingAlgorithmOr the data structure is used to characterize the thread, but as a process that shares resources with other processes; different from other systems.
The differences between kernel threads and common processes are:
The kernel thread does not have an independent address space.
Runs only in the kernel space and does not switch to the user space
5. Process Termination
When a process ends, the kernel releases its resources and tells the parent process to update the parent-child relationship. Call exit to terminate the process. Usually, do_exit must be called at the end of the process.
Void Do_exit ( Long Code ){ // Obtain the current running process Struct Task_struct * tsk = Current ;...... // Sets pf_exiting Exit_signals (TSK ); // Release task_struct mm_struct memory Exit_mm (TSK ); // Exit the receiving IPC signal queue Exit_sem (TSK ); // Process namespace Exit_shm (TSK ); // File descriptor Exit_files (TSK ); // File System Exit_fs (TSK ); // Resource release Exit_thread (); // Send a signal to the parent process Exit_policy (tsk, group_dead );...... // Switch to another process Tsk -> State = Task_dead; TSK -> Flags | = Pf_nofreeze; schedule ();......}