The first assignment: in-depth source code analysis process model (linux)

1. What is a process

  There are many softwares that can be run on the computer, including the operating system. When these softwares run, one or more processes are generated.

2. Organization and conversion of processes in Linux system

1> The descriptor of the process in Linux (that is, the structure used to describe a process)

struct task_struct {

    ......

    volatile  long state;                    // Describe the running state of the process

    void *stack;                            // point to the kernel stack

    struct list_head tasks;                 // Used to join the process list 
    ...

    struct mm_struct *mm, *active_mm;       // points to the memory area descriptor of the process

    ......

    pid_t pid;                              // Process ID 

    pid_t tgid;                             // Thread group ID

    struct pid_link pids[PIDTYPE_MAX];      // Used to connect to PID, TGID, PGRP, SESSION hash table

    ........

    struct task_struct __rcu *real_parent; // Point to the parent process that created it, or point to the init process if its parent process does not exist
  
    struct task_struct __rcu *parent;       // points to the current parent process, usually consistent with real_parent
    
    struct list_head children;              // child process list

    struct list_head sibling;               // sibling process list

    struct task_struct *group_leader;       // Thread group leader thread pointer

    struct thread_struct thread;            // Save hardware context during process switch

    struct fs_struct *fs;                   // current directory

    struct files_struct *files;             // Point to the file descriptor, all open files of the process will be in an array of pointers inside

    ........

  struct signal_struct *signal;           // Signal descriptor

  struct sighand_struct *sighand;         // Signal handler function descriptor

  sigset_t blocked, real_blocked;
  /* sigset_t is a bit array, each signal corresponds to one bit, the maximum number of signals in linux is 64
   * blocked: blocked signal mask
   * real_blocked: Temporary mask for blocked signals
   */  

  sigset_t saved_sigmask;                 // set_restore_sigmask() is used to restore

  struct sigpending pending;              // private pending signal queue

    ........
}

  In a process descriptor, contains all the information of the process. In the kernel, there will be a process linked list linking the process linked list of all processes by using the tasks structure in the process descriptor.

  PID is a process identifier, which is unique like a student's student ID. Under normal circumstances, the PID numbers are sequential, but there is an upper limit. After the upper limit is reached, the cycle starts to search for idle PID values.

  Relationship between processes:

  A process is mostly created by another process, and these created processes have a parent-child relationship with the process that created them.

  If a process creates multiple processes, these processes are siblings.

  And if a process P0 creates processes P1, P2, and P3, and process P3 creates process P4, their entire linked list is as follows:

  

2> The state of the process in Linux

  TASK_RUNNING: Ready state or running state, the process is ready to run, but not necessarily occupying the CPU

  TASK_INTERRUPTIBLE: Sleep state, light sleep, can respond to signals

  TASK_UNINTERRUPTIBLE: Sleep state, deep sleep, do not respond to signals, the typical scenario is that the process gets blocked by the semaphore

  TASK_STOPED: Stop state, when the process receives a SIGSTOP, SIGTSTP, SIGTTIN or SIGTTOU signal to enter

  TASK_ZOMBIE: Zombie state, the process has exited or ended, but the parent process does not know it yet, the state when there is no recycling

3> Conversion of processes in Linux

  In Linux, all switch to() is used to complete the process of switching from prev to next

switch to() macro source code:

 

#define switch_to(prev,next,last) do { \
unsigned long esi,edi; \
asm volatile("pushfl\n\t" \
    "pushl %%ebp\n\t" \
    "movl %%esp,%0\n\t" /* save ESP */ \
    "movl %5,%%esp\n\t" /* restore ESP */ \
    "movl $1f,%1\n\t" /* save EIP */ \
    "pushl %6\n\t" /* restore EIP */ \
    "jmp __switch_to\n" \
    "1:\t"  \
    "popl %%ebp\n\t" \
    "popfl"  \
    :"=m" (prev->thread.esp),"=m" (prev->thread.eip), \
     "=a" (last),"=S" (esi),"=D" (edi) \
    :"m" (next->thread.esp),"m" (next->thread.eip), \
     "2" (prev), "d" (next)); \
} while (0)

 

  This macro has three parameters:

  prev: This parameter stores the current process descriptor pointer

  next: This parameter stores the pointer of the new process that needs to be replaced

  last: This parameter stores the pointer of the process that occupied the CPU before the current process

Linux process conversion diagram:

 

 4> Organization of the process

  All creations in TASK_RUNNING will be put into the CPU's run queue, and they can be in different CPU run queues. The process in TASK_STOPED does not establish a special linked list, but it can be accessed through the PID and the parent-child linked list. Processes in the TASK_INTERRUPTIBLE and TASK_UNINTERRUPTIBLE states will be put into the corresponding waiting queues, and the wake-up conditions of each waiting queue are different.

3. How Linux processes are scheduled

1> Linux process priority

  Linux processes can be divided into two types by scheduling priority: real-time processes and ordinary processes. In any case, real-time processes have higher priority than normal processes.

2> Scheduling of real-time processes

  Real-time processes have only static priorities, and those with higher priorities always run before those with lower priorities. When two processes have the same priority, the processes are executed in the order on the queue.

3> Scheduling of ordinary processes

  Ordinary processes are scheduled by dynamic priority. The dynamic priority is adjusted from the static priority. The second Linux system gives the user an interface that can adjust the static priority: the nice value. The relationship between static priority and nice value is:

  static_prio=MAX_RT_PRIO +nice+ 20

  The range of nice values ​​is -20~19, so the static priority range is between 100~139. The larger the nice value, the larger the static_prio, and the lower the final process priority.

  The formula for calculating dynamic priority is:

  dynamic_prio = max (100, min (static_prio - bonus + 5, 139))

  bouns is the average sleep time of the process

4. Experience

  As a representative operating system, Linux has undergone many years of updating and optimization. In this assignment, I analyzed the organization, conversion and scheduling of processes in the operating system, and understood that the Linux system can achieve the highest utilization efficiency of the CPU without affecting the effect by adjusting the process. Through this assignment, I learned what conditions an excellent operating system should have, and my understanding of the operating system was deeper.

5. Reference link

  https://blog.csdn.net/kklvsports/article/details/52268085

  https://www.cnblogs.com/tolimit/p/4530370.html

  http://blog.chinaunix.net/uid-23253303-id-3952935.html

  http://www.cnblogs.com/zhaoyl/archive/2012/09/04/2671156.html

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325213970&siteId=291194637