The process of creating a new process for the Linux kernel

Source: Internet
Author: User
Tags signal handler

The process begins to survive at the moment it is created. In a Linux system, this is usually the result of a fork () system called to create a completely new process by copying an existing process. The data structure is populated by code only when the init process is created. The process calling fork () is called the parent process, and the new process is called a child process. At the end of the system call, at the same location as the return point, the parent process resumes execution and the child process begins execution. The fork () system call returns from the kernel two times: once back to the parent process, and another time back to the new child process that was created.

Process Descriptor--task_struct (below is a general comment in English and Chinese)

volatile LongState/*-1 unrunnable, 0 runnable, >0 stopped*/Status of the process
void *stack; The process allocates its kernel stack through the Alloc_thread_info function and frees the allocated kernel stack through the Free_thread_info function.
unsigned int flags; /* per process flags, defined below */Process label
 
Scheduling of processes
int ON_RQ;
int Prio, Static_prio, normal_prio;//process priority real-time priority range is 0 to max_rt_prio-1 (i.e. 99), while the normal process's static priority range is from Max_rt_prio to Max_ PRIO-1 (i.e. 100 to 139). The higher the value, the lower the static priority.
The unsigned int rt_priority;//rt_priority is used to hold the real-time priority. The Normal_prio value depends on the static priority and scheduling policy, Static_prio is used to hold the static priority and can be modified through nice system calls.
const struct Sched_class *sched_class;//sched_class struct represents the dispatch class
struct sched_entity se;
struct sched_rt_entity RT;
struct sched_dl_entity dl;
unsigned int policy; Policy represents the scheduling strategy for a process
int nr_cpus_allowed;
The cpumask_t cpus_allowed;//cpus_allowed is used to control where the process can run on the processor.
struct List_head tasks; To build the process chain list, the kernel of the bidirectional loop linked list implementation Method-a more abbreviated two-way circular linked list
struct Mm_struct *mm, *active_mm;//mm points to the memory descriptor owned by the process, and active_mm points to the memory descriptor used by the process when it runs. For normal processes, the values of the two pointer variables are the same. However, kernel threads do not own any memory descriptors, so their mm members are always null. When a kernel thread is running, its ACTIVE_MM member is initialized to the ACTIVE_MM value of the previous running process.
/* Per-thread VMA caching */
U32 Vmacache_seqnum;
struct vm_area_struct *vmacache[vmacache_size];
/* Task State */
int exit_state;
int Exit_code, Exit_signal;//exit_code is used to set the termination code of the process, either _exit () or exit_group () system call parameters (normal termination) or an error code supplied by the kernel (abnormally terminated).
int pdeath_signal; /* The signal sent when the parent dies *///exit_signal is set to 1 indicates that it is a member of a thread group. Only when the last member of a thread group terminates will a signal be generated to inform the parent process of the thread group's lead process.
unsigned int jobctl; /* jobctl_*, siglock protected */

/* Used for emulating ABI behavior of previous Linux versions */
unsigned int personality;

unsigned in_execve:1; /* Tell the LSMS, the process is doing an
* EXECVE * *
unsigned in_iowait:1;

/* Revert to default Priority/policy when forking */
unsigned sched_reset_on_fork:1;
unsigned sched_contributes_to_load:1;
unsigned long atomic_flags; /* Flags needing atomic access. */

pid_t pid; Process identification number
pid_t Tgid;
/* The process created by the program has a parent-child relationship, and it is often necessary to reference such a parent-child relationship when programming. There are several fields in the process descriptor that are used to represent such relationships
* Pointers to (original) The parent process, youngest child, younger sibling,
* older sibling, respectively. (P->father can replaced with
* p->real_parent->pid)
*/
struct task_struct __rcu *real_parent; /* Real Parent process */
struct task_struct __rcu *parent; /* recipient of SIGCHLD, WAIT4 () reports */
/*
* Children/sibling forms the list of my natural children
*/
struct List_head children; /* List of my children */
struct List_head sibling; /* Linkage in my parent ' s children list */
struct Task_struct *group_leader; /* Threadgroup leader */
cputime_t Utime, Stime, utimescaled, stimescaled;//utime/stime are used to record the number of Beats (timers) that the process passes through in the user state/kernel state. The utimescaled/stimescaled is also used to record the elapsed time of the process in the user state/kernel state, but they are scaled at the processor frequency.
cputime_t Gtime;//gtime is the virtual machine runtime (guest time) counted in Beats.
unsigned long NVCSW, NIVCSW; /* Context Switch counts */
U64 start_time; /* monotonic time in NSEC */
U64 Real_start_time; /* Boot based time in NSEC */
/* mm fault and swap info:this can arguably be seen as either mm-specific or thread-specific */
unsigned long min_flt, Maj_flt;

struct Task_cputime cputime_expires;
struct List_head cpu_timers[3];

/* Process Credentials */
const struct CRED __rcu *real_cred; /* Objective and real subjective task
* Credentials (COW) * *
const struct CRED __rcu *cred; /* Effective (overridable) subjective task
* Credentials (COW) * *
Char Comm[task_comm_len]; /* Executable name excluding path
-Access with [Gs]et_task_comm (which lock
It with Task_lock ())
-Initialized normally by setup_new_exec */
/* File System Info */
int Link_count, Total_link_count;
/* Cpu-specific State of this task */
struct THREAD_STRUCT thread;
/* FileSystem information */
struct Fs_struct *fs;
/* Open File Information */
struct Files_struct *files;
/* Namespaces */
struct Nsproxy *nsproxy;
/* Signal handlers */
The struct signal_struct *signal;//signal a signal descriptor that points to the process.
The struct sighand_struct *sighand;//sighand a signal handler descriptor that points to the process.

sigset_t blocked, real_blocked;//blocked represents the mask of the blocked signal, and real_blocked represents a temporary mask.
sigset_t Saved_sigmask; /* restored if Set_restore_sigmask () was used */
struct sigpending pending; Pending the data structure that holds the private suspend signal.

unsigned long sas_ss_sp;//sas_ss_sp is the address of the signal handler standby stack, and sas_ss_size represents the size of the stack.
size_t Sas_ss_size;
Int (*notifier) (void *priv);
void *notifier_data;//device drivers commonly use notifier-pointing functions to block certain signals of a process (Notifier_mask are bitmask of these signals), Notifier_ Data refers to what the function that notifier points to might use.
sigset_t *notifier_mask;
struct Callback_head *task_works;

struct Audit_context *audit_context;//Process Audit
/* THREAD Group Tracking */
U32 parent_exec_id;
U32 self_exec_id;
/* Protection of (de-) allocation:mm, files, FS, TTY, keyrings, mems_allowed,
* Mempolicy * *
spinlock_t Alloc_lock;

/* Protection of the PI data structures: */
raw_spinlock_t Pi_lock;
/* journalling FileSystem Info */
void *journal_info;

/* Stacked block Device Info */
struct Bio_list *bio_list;
/* VM State */
struct Reclaim_state *reclaim_state;

struct Backing_dev_info *backing_dev_info;

struct Io_context *io_context;

unsigned long ptrace_message;
siginfo_t *last_siginfo;  /* for ptrace use. */
struct task_io_accounting IOAC;
struct Rcu_head RCU;

/*
* Cache last used pipe for splice
*/
struct Pipe_inode_info *splice_pipe;

struct Page_frag Task_frag;
/*
* Time slack values; These is used to round up poll () and
* Select () etc timeout values. These is in nanoseconds.
*/
unsigned long Timer_slack_ns;
unsigned long Default_timer_slack_ns;
Assigning process descriptors

Linux allocates the TASK_STRUCT structure through the slab allocator, which can achieve object reuse and cache coloring.

structThread_info {structTask_struct *task;/*main task Structure*/    structExec_domain *exec_domain;/*execution Domain*/unsignedLongFlags/*Low level flags*/__u32 status; /*Thread Synchronous Flags*/__U32 CPU; intPreempt_count;/*0 = preemptable, <0 = BUG*/mm_segment_t Addr_limit; /*Thread address space*/    structRestart_block Restart_block; unsignedLongPREVIOUS_SP;/*sp of previous stack in case of nested IRQ stacks*/__u8 supervisor_stack[0];};

Status of the process:
Include/linux/sched.h
#define task_running 0#define task_interruptible 1#define task_uninterruptible 2#define __task_stopped 4#define __task_traced 8

Creation of processes

Linux implements fork () through clone () system calls. Then there is clone () to call Do_fork (). Do_fork () completes most of the work in the creation, which is defined in the Kernel/fork.c file. Call the Copy_process () function, create a child process descriptor with copy_process (), and create additional data structures that are required for the child process to execute, eventually returning the created process descriptor (the child process descriptor).

p = copy_process (Clone_flags, Stack_start, Stack_size,child_tidptr, NULL, trace);//struct task_struct *p;

Call Dump_task_struct () in the copy_process () function.

In the copy_process () function
p = dup_task_struct (current); // struct task_struct *p; = Copy_thread (Clone_flags, Stack_start, Stack_size, p);

Dump_task_struct ()

Dump_task_struct () Creates a kernel stack, thread_info structure, and task_struct for the new process with the same values as the current process, at which time the parent-child process's descriptor is identical.

//In the Dump_task_struct () function 
Tsk = alloc_task_struct_node (node); struct task_struct *tsk; ti = Alloc_thread_info_node (tsk, node); // struct thread_info *ti; err = arch_dup_task_struct (tsk, orig); // int err;
Tsk->stack = ti;
Setup_thread_stack (tsk, orig);
#define alloc_task_struct_node (node)                        \({                                            struct page *page = Alloc_pages_node ( node, Gfp_kernel | __gfp_comp,                             Kernel_stack_size_order);             struct task_struct *ret = page? page_address (page): NULL;                                                    ret;                                    })

Create a page in the Alloc_task_struct_node (node) function, which is part of the stack

Arch_dup_task_struct (struct task_struct *dst, struct task_struct *src) functions copy a pcb--task_struct

In arch_dup_task_struct (struct task_struct *dst, struct task_struct *src) function
*DST = *SRC; // in the Arch_dup_task_struct () function, the copy operation is done by assigning a value

The Setup_thread_stack () function simply replicates the thread_info, not the kernel stack

Static void setup_thread_stack (structstruct task_struct *org) {    *task_thread_info (p) = *task_thread_info (org);    Task_thread_info (p)->task = p;}
Copy_thread () function

In the Copy_thread () function, complete the initialization

//In Copy_thread (unsigned long clone_flags, unsigned long sp,unsigned long arg, struct task_struct *p) function
structPt_regs *childregs =Task_pt_regs (P);//Stack bottom of the kernel stack, p represents the child processstructTask_struct *tsk; interr; P-&GT;THREAD.SP = (unsignedLong) Childregs; P->thread.sp0 = (unsignedLong) (childregs+1);
if (Unlikely (P->flags & Pf_kthread)) {//copy part of int instruction and Save_all stack content
/* Kernel thread */
memset (childregs, 0, sizeof (struct pt_regs));
P->thread.ip = (unsigned long) ret_from_kernel_thread;
Task_user_gs (p) = __kernel_stack_canary;
Childregs->ds = __user_ds;
Childregs->es = __user_ds;
Childregs->fs = __KERNEL_PERCPU;
CHILDREGS-&GT;BX = SP; /* Function */
CHILDREGS-&GT;BP = arg;
Childregs->orig_ax =-1;
Childregs->cs = __kernel_cs | GET_KERNEL_RPL ();
Childregs->flags = x86_eflags_if | x86_eflags_fixed;
P->thread.io_bitmap_ptr = NULL;
return 0;
}
*childregs = *current_pt_regs ();//copy kernel stack
Childregs->ax = 0;//Why the fork of the subprocess returns 0, here is the reason!
if (SP)
CHILDREGS-&GT;SP = sp;//The top of the kernel stack when dispatching to a child process
P->thread.ip = (unsigned long) ret_from_fork; The address of the first instruction when dispatched to a child process

Reference documents:

http://blog.csdn.net/npy_lp/article/details/7335187

Process of creating a new process by the Linux kernel

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.