Process _Linux kernel design and implementation notes

process

Is the general term for the process of the program and related resources in the implementation phase, the result is real-time code being executed.

Part of the PM process located Kernel layer process is an abstraction of the Unix operating system, the most basic one, the operating system exists to run user programs, so the operating system process management is all heart lies.
Program itself is not the process, the process not limited to executable code segment (text section), complete a number of different processes that may occur, is performed the same program, between multiple processes can share some resources, such as opening a file, the address space.

Thread

Thread of execution threads for short, is a process of active objects, each thread has 独立的程序计数器, 进程栈, and 一组进程寄存器.

Scheduling objects are in the process of active objects 线程, rather than the process itself, a process usually contain multiple threads, that is 多线程序.

Virtual processors and virtual memory

Process provides two mechanisms, 虚拟处理器and 虚拟内存actually may be many processes share the same processor, the processor will process the virtual felt in the exclusive processor, virtual memory Similarly, the process will feel that they have the memory resources of the entire system.

Virtual memory can be shared between threads contained in the same process, but each thread has its own virtual processor.

From the kernel's point of view, there is no concept of threads, threads for Linux is just a means of sharing resources between processes.

Create a process

Creating processes using the fork function

...
NAME
   fork - create a child process

SYNOPSIS
   #include <sys/types.h>
   #include <unistd.h>

   pid_t fork(void);

DESCRIPTION
   fork()  creates  a new process by duplicating the calling process.  The new process is
   referred to as the child process.  The calling process is referred to  as  the  parent
   process.

   The  child  process and the parent process run in separate memory spaces.  At the time
   of fork() both memory spaces have the same  content.   Memory  writes,  file  mappings
   (mmap(2)),  and unmappings (munmap(2)) performed by one of the processes do not affect
   the other.
   ...
   RETURN VALUE
   On  success, the PID of the child process is returned in the parent, and 0 is returned
   in the child.  On failure, -1 is returned in the parent, no child process is  created,
   and errno is set appropriately
   ...

fork函数  
Creat thread   
child process may use all of father's resources  
pid_t fork(void);  
– 参数:无  
– 返回值:执行成功,返回子进程pid给父进程,0返回给子进程;出现错误,返回-1给父进程。执行失败的唯一情况是内存不够或者id号用尽,不过这种情况几乎很少发生。  
– 系统函数fork 调用成功,会创建一个新的进程,它几乎会调用差不多完全一样的fork 进程  
– 子进程的pid 和父进程不一样,是新分配的  
– 子进程的ppid(他爷爷的ID) 会设置为父进程的pid,也就是说子进程和父进程各自的
“父进程”不一样.  
– 子进程中的资源统计信息会清零.  
– 挂起的信号会被清除,也不会被继承.  
– 所有文件锁也不会被子进程继承.  

Process process begins at the time it was created to survive, Linux usually to create a process using fork () system call, the system call to create a new process by copying an existing process calls fork () process is called the parent process, the new process is called the child process created after the end of the call, return to the parent process, the parent process continues downward, the child process begins execution,

父进程调用子进程,然后自己向下执行,同时子进程被调用后也开始执行.
fork系统调用从内核返回两次,一次返回到父进程,另一次返回到新产生的子进程.

Typically, create a new process is to implement the new program immediately, using the exec function cluster can create a new address space, and the program (executable file) loaded; fork function is actually a clonesystem call implementation.

clone()的所有参数定义在 linux/sched.h 中.

Call relationship

创建进程 -> fork() -> clone() -> do_fork() -> copy_process()

copy_process () function to complete

  1. Call dup_task_struct () to create a kernel stack, and create thread_info structure task_struct structure.
  2. Check to make sure that the current number of processes does not exceed the limit.
  3. The child themselves and the parent process can be distinguished. Many members of the (statistical information) process descriptor will be set to an initial value.
  4. Status of the child process is set to TASK_UNINTERRUPTIBLE, to ensure that it can not be put into operation.
  5. copy_process call copy_flags (), update the flags of the members of task_struct.
  6. Call alloc_pid () to assign a valid PID for the new process.
  7. The parameters passed clone flag, copy_process copied or shared open files.
  8. Mop-up work, returns a pointer to the child process.

Back do_fork function, the function returns if copy_process success, the kernel will intentionally let the child process to execute, usually the child process calls exec immediately this will avoid copy-on-write overhead.

Process descriptor

Another process is the task name task, said from the perspective of the kernel developer's task, usually seen for all processes starting from the kernel, the kernel is called the process list on 任务队列two-way circular linked list in which each type of are task_structknown as process descriptor ( process descriptor) structure, which is defined in the configuration <linux/sched.h>file, the process descriptor contains a specific process information.

/*进程描述符task_struct结构*/
struct task_struct {
#ifdef CONFIG_THREAD_INFO_IN_TASK
    /*
     * For reasons of header soup (see current_thread_info()), this
     * must be the first element of task_struct.
     */
    struct thread_info      thread_info;
#endif
    /* -1 unrunnable, 0 runnable, >0 stopped: */
    volatile long           state;

    /*
     * This begins the randomizable portion of task_struct. Only
     * scheduling-critical items should be added above here.
     */
    randomized_struct_fields_start

    void                *stack;
    atomic_t            usage;
    /* Per task flags (PF_*), defined further below: */
    unsigned int            flags;
    unsigned int            ptrace;
    /*
     * WARNING: on x86, 'thread_struct' contains a variable-sized
     * structure.  It *MUST* be at the end of 'task_struct'.
     *
     * Do not put anything below here!
     */
};

task_structIs relatively large, because this structure contains all the information required for a process management kernel, the data contained in the process descriptor can be a complete description of the program being executed, the process descriptor including:

  • The process open files,
  • Process's address space,
  • Pending signal,
  • State of the process and so on.

Allocation process descriptor

By Linux slabdistribution task_structstructure, this can reach 对象复用and 缓存着色(cache coloring). Use slabdynamically generated task_structstructure, simply create a new stack top or bottom of the stack structure struct thread_info.

On the x86 platform struct thread_infofiles defined in <asm / thread_info.h> in

currentGet the program currently running process descriptor

In the kernel access tasks often need to point his task_structpointer, the vast majority of the kernel code is processed by the process are task_structcarried out, you can current宏find the processes that are currently running process descriptors.

This macro depending on the hardware architecture, implementation is different 1 :
Some hardware architecture can use a special register to store the address, to achieve such a current task_struct structure, will be very easy, direct return value of the register on the line, but some registers less hardware architecture, we can only thread_info by creating a structure, offset by calculating the indirect address lookup task_struct structure.

current宏Two ways to achieve:

  1. Find an indirect process descriptor by thread_info structure.
  2. By storing special process described direct return value registers to find the identifier process descriptor.

thread_info structure

Header file path:

.\linux源码目录\arch\arm\include\asm\thread_info.h
/*
 * low level task data that entry.S needs immediate access to.
 * __switch_to() assumes cpu_context follows immediately after cpu_domain.
 */
struct thread_info {
    unsigned long       flags;      /* low level flags */
    int         preempt_count;  /* 0 => preemptable, <0 => bug */
    mm_segment_t        addr_limit; /* address limit */

    struct task_struct  *task;      /* main task structure */
    __u32           cpu;        /* cpu */
    __u32           cpu_domain; /* cpu domain */
    struct cpu_context_save cpu_context;    /* cpu context */
    __u32           syscall;    /* syscall number */
    __u8            used_cp[16];    /* thread used copro */
    unsigned long       tp_value[2];    /* TLS registers */
#ifdef CONFIG_CRUNCH
    struct crunch_state crunchstate;
#endif
    union fp_state      fpstate __attribute__((aligned(8)));
    union vfp_state     vfpstate;
#ifdef CONFIG_ARM_THUMBEE
    unsigned long       thumbee_state;  /* ThumbEE Handler Base register */
#endif
};

Each task thread_infostructure created at the end of his kernel stack. Structure task域stored pointer to the task is actually task_structa pointer through pre-assigned, and reuse task_structof resources, dynamic allocation and release can be avoided caused by consumption. Architecture register weaker than introduce thread_infoa unique structural reasons, this new structure make the calculation easier compiled in assembly code.

PID storage

I.e. the kernel process by a unique identification value (process identification value) PIDto represent each process. PIDIs a number, expressed as pid_t隐含类型2 , it is actually a type int. For compatibility with older versions of Unix and Linux, PID maximum default setting is 32768 (short int maximum short integer), this limit is defined in <linux/threads>the. The kernel of each process PIDis stored in their own process descriptor.

This PIDlimit (the process allows the maximum number of simultaneous presence of) the smaller, faster turn around (process execution cycle lap), usually large numerical processes running after small value process (program to run with a smaller PID values because the PID value increment distribution), if need to modify the pidlimits, you can modify /proc/sys/kernel/pid_maxraise the ceiling

state domain

Process descriptor state域describes the current state of the process, each process in the system are inevitable in the process of one of five states:

  1. TASK_RUNNING run: process being executed or awaiting execution.
  2. TASK_INTERRUPTIBLE interruptible: sleep process is blocked, waiting for the fulfillment of the conditions to be awakened state to run.
  3. TASK_UNINTERRUPTIBLE uninterruptible 3 : Even if the received signal will not be awakened.
  4. __TASK_TRACED tracked process other processes, such as by ptracetracking debug procedures.
  5. __TASK_STOPPED process stops execution 4 , the process is not put into operation.

Set the current process status

Function adjustment of status process

set_task_state(task,state)/*将任务task的状态设置为state*/  

This function specified process to the specified state, in an SMP system, will set the memory barrier to force the other processors for re-ordering, or equivalent

task->state = state;/*设置状态位的状态为state*/

set_current_state (state) and set_task_state (current, state) have the same meaning, particularly in the header file <linux/sched.h>in.

NOTE: task domain is located thread_info configuration, a pointer to point to the process described task_struct structure identifier.

The difference between the fork and vfork

copy when fork function copy of the parent process to a child process page table entry, the page table entries have not written
vfork page table entry function does not copy the parent process (),

fork copy of the current process, create a child process
vfork with fork but after the parent process waits for the child process exits continue
to run in his address space in a separate thread to do the parent process child process, the parent process is blocked until the child process exit

Page table entry

In order to facilitate the management of the operating system memory address, the memory address is divided into a number of pages, the address of each page, that is, a page table entry.

Kernel threads

Kernel threads are independent standard processes running in kernel space, the difference between a normal process is that it does not separate address space, 5 all kernel threads are running in the same address space.

Check kernel threads command:

ps -ef 

Create a kernel thread

linux/kthread.hIs provided to create a new kernel thread from the existing kernel thread method
--- kthread_createfunction, a newly created process in the state can not run, if not by calling wake_up_processclear wake it up, he would not run.

By kthread_runcan be implemented to create a process and wake it up, this is the package for the above two functions,

#define kthread_run(threadfn, data, namefmt, ...)              \
({                                     \
    struct task_struct *__k                        \
        = kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \
    if (!IS_ERR(__k))                          \
        wake_up_process(__k);                      \
    __k;                                   \
})

In order to improve the operating efficiency of the code, the kernel function uses a lot of macro package, this time minus the overhead of function calls needed.

End of kernel threads

After the kernel thread starts, it will run until calling do_exit()exit, or other parts of the kernel calls the kthread_stopexit, at the end of the process, the kernel must release all his resources, and inform the parent process, the process of destruction is generally caused by itself, it display or implicit call exitsystem call, end their own, C compiler will return to the main point is placed behind the function of exitabnormal system call code to achieve implicit call to exit, or process, passive end.

No matter how the end of the process, the task will be made do_exitto complete the system call 6 .

do_eixtfinished work

  1. The members of task_struct flag is set to PF_EXITING. (Setting process descriptor flags off mark)
  2. Call del_timer_sync () delete any of the core timer, make sure that no timer in the queue, there is no timer handler runs.
  3. If the BSD process accounting function is enabled, do_exit () call acct_update_integrals (), output billing information
  4. Call exit_mm () function to release occupied by the process mm_struct, if nothing else the process they use (stating that your memory is not shared), completely release them.
  5. Call sem__exit () function, if the process signal IPC waiting in line, then leave the queue
  6. Call exit_files () and exit_fs (), respectively decreasing and file system file descriptor reference count, if the reference count drops to 0, the process does not use the appropriate resources can be released.
  7. Will be stored in exit_code task_struct members of the task exit code set by the exit () provides an exit code, or to complete the exit action under any other kernel mechanism, the exit code stored here for retrieval at any time the parent process.
  8. Exit_notify call notifies the parent process, the child process to find adoptive father, (the parent process to end, then he must be the child of his following, find adoptive father, otherwise he would have the following sub-processes become orphaned), can be a father ancestors Init can also be other processes. exit_state settings and process state task_struct structure is EXIT_ZOMBLE.
  9. do_exit call schedule switch to the new process (call scheduler, to give up processor time to let the scheduler to schedule other processes), because the state is in the process of EXIT_ZOMBIE will not be scheduled, so this is the last piece of code executed by the process, do_exit never returned.

    flags flags are defined in <linux \ sched.h> in.

    /*
    * Per process flags
    */
    #define PF_IDLE         0x00000002  /* I am an IDLE thread */
    #define PF_EXITING      0x00000004  /* Getting shut down */
    /*...*/

If the process and the resources are not shared, then all the related resources are freed up, and in EXIT_ZOMBIE exit status, all memory is the kernel stack, thread_info task_struct structure and structure it occupies,
the sole purpose of the process at this present is to after providing information to the parent, the parent process to retrieve the information, confirmed that he had died, for it to do deal with the aftermath, which was held in the memory of all the rest returned to the system.

In the do_exitfollowing, the parent process as before for it to do deal with the aftermath, although the process has been dead can not run, but the system still retains his process descriptor, this allows the system to have a way to still be able to get his message after the end of the child process after clean-up work, that is the end of the process, and the process descriptor delete work is performed separately until the parent process to retrieve the child had died of the information or inform the kernel that it is not concerned about what information the child process task_structstructure was only freed

Rid of zombie processes

---释放进程描述符

Parent process by wiat4 responsible for implementing the system calls dealing with the aftermath of the child, his standard action:

  • It hangs calling process until one of its child process exits, then the function will return the PID of the child process,
  • Provided when calling the function pointer contains the exit code when the subroutine exits.
  • When the final release process descriptor, will call release_task, he completed:
  1. Call _exit_signalfunction, the function call _unhash_process, the latter calling detach_pidfrom function pidhashto delete the process on, but also to remove the process from the task list.
  2. _exit_signal release all remaining resources currently zombie processes and final statistics and records.
  3. If this process is the last process thread group, and lead the process dead, it release_taskwill notify the parent process dead leading the process.
  4. release_task call put_task_structrelease 进程内核栈and thread_info结构share pages, and release calls the tast_structshare of slabhigh-speed cache.

At this point 进程描述符all processes on all exclusive resources freed up.

Orphaned, dilemma

Parent before the child process exits, you must find a father to him, otherwise the process will always be orphans in dead state on exit because there is no parent process to retrieve information about their deaths, and they deal with the aftermath (deletion process description Fu).
this is not only a waste of system resources, and the cost of memory in vain,
the solution is the parent process at the time of his death, found him a process in the current thread group to find him father, not to find ancestors init process.

do_exitWill call exit_notifythe function call forget_original_parent, which calls back find_new_reaperto find the parent process execution, this CODE will foster father found him in the current thread group, if not to find Init.


summary:

  • Each thread has a separate program counter, process stack, and a set of processes register.
  • Process provides two mechanisms, virtual processors and virtual memory,
  • Kernel thread for it is only a means of shared memory
  • Create a process,fork
  • The executable file is loaded into memory space is running,exec
  • Obtain the process descriptor,current宏
  • current宏Depending on the implementation of a hardware configuration, there are two implementations.
  • Process descriptor structure task_struct
  • PID of each process is stored in the respective process descriptor
  • Process descriptor state field describes the current state of the process,
  • Five states process
  • State setting process
  • Check kernel threads
  • Create and wake kernel threads kthread_run
  • End of kernel threads exit
  • Page table entry

The relationship between processes

There are obvious inheritance relationship between processes, all processes are descendants of init process PID is 1, each process must have a parent process and any child processes.

Storage and that the process of

The relationship between processes is stored in the process descriptor task_struct, each task_structcontains a pointer pointing to the parent process parentand a child process a pointer points children.

current宏

current宏The process used to find the currently running process descriptors task_struct, specific implementation structure varies depending on the machine.

Creation process

The process of creating a process for creating a new address space in the process of reading and executing the executable file; Linux, this step may be divided into two functions, fork in charge copy of the current process as a child process (create a new process), (fork not read the executable file and functions), the executable file is read by the exec function in the child process (new process) and begin execution.

When writing copy

If the child does not need the resources of the parent process, then a copy of the parent's resource fork is white work, so when the copy has been written, only when the child needs, only to copy the parent, if the child process immediately calls exec function, execute the executable file, and quit, you do not need to copy the resources of the parent process.

Thread

In Linux thread is a special process, is a means of sharing resources, the same process can contain multiple threads can share the same resources among multiple threads 7 .

wait system call

wait action is pending call it the process which is the process once called wait, immediately blocking their own, waiting for one of its child process exits, it will wait to gather information and put the child process after it returns to complete destruction, a return to normalcy .

Means offspring parent process to collect information

The kernel is responsible for implementing wait4the system call, Linux is usually provided by the C library (wait family of functions) wait, waitpid, wait3, wait4functions that have nuances, but are able to achieve the return status on the termination of the process.

Parent process through wait4a system call queries the child process if an end, which makes the process has the ability to wait for a specific process is finished, the process exits after executing, it will be set to zombie state until his parent calls wait(), or waitpidfar, only a complete end .

By blocking its own until the end of the child process, wait function will do to deal with the aftermath of the end of the child process (destruction, deletion process descriptor, release all his resources).

How the process of dying

Or exit the program by displaying the system call implicit call to withdraw from the 8 , this function will be the end of the process, and it takes resources released. At this time, the thread is dead state, and is not able to run. Need to wait for the family of functions progress toward destruction.



  1. Such as the realization of the x86 architecture current macro. In PPC, there are a sufficient number of registers, and because access to the process descriptor is an important frequent operation, so the PPC kernel developers for the process descriptor alone has opened a register, current macro just to return to the line of the stored value of the register r2 task_struct structure address.

  2. Implicitly refers to the data type represents a type of physical unknown or irrelevant.

  3. The state usually must be undisturbed while waiting for the process, or wait for the event will soon take place; in this state because the task does not respond to the signal, less used, because the reception in this state, any process the signals are not respond, even when using the pscommand to see is marked as Dthe cause but can not kill you send SIGKILL信号, he will ignore off. typically the process of this state should have something important is not processed, may even hold a semaphore, it should not be forced to find a way to kill him.

  4. This state typically occurs upon receiving SIGSTOP, SIGSTP, SGITTIN, SIGTTOU other signals, in addition to receiving any signal, when the process will enter this state during debugging.

  5. Linux is a single-kernel operating system.

  6. Although people sad, but after all, it is to end the process.

  7. Linux in the process and the concept of threads is very vague, not deliberately distinguish between threads and processes, threads are merely a means of sharing resources Bale.

  8. Explicit or implicit call; implicit call: the compiler returns the exit system call is added portion main function.

Guess you like

Origin www.cnblogs.com/lifo/p/11791605.html