当前位置:网站首页>[Linux] process control and parent-child processes

[Linux] process control and parent-child processes

2022-07-07 07:24:00 People in the shadow LX

1. Processes and procedures

1.1 The concept of process and program

The concept of procedure : A program is a document , Compiled binary files

process : Running program .

  • From a programmer's point of view , Is the process of running a series of instructions

  • From the perspective of the operating system : The basic unit for allocating system resources
    difference :

  • The program takes up disk resources , Do not occupy the resources of the system

  • Memory takes up system resources

  • A program can correspond to multiple processes , And a process corresponds to a program .

  • So the program has no life cycle , But processes have a life cycle .

1.2 Single channel and multi-channel programming

Single channel programming : Only one program is running at a time ; Other programs are waiting .(DOS)

Multiprogramming : Design a time slice , Execute a program in a time slice , In the next time slice, immediately switch to the next program , To give way to cpu Resources for other programs .

Because the time of a time slice is very short , It belongs to the millisecond level . So in human perception , Several programs are performed concurrently ; But at the micro level , On a time slice , Only one program is running . Micro serial , Macro parallel

image-20220705013224488

1.3 Transition of process state

cpu and MMU( Memory management unit )

image-20220705014033454

  • Registers are the fastest
  • Alu can only continue + The calculation and << operation
1.3.1 Process state switch

image-20220705015259759

1.3.2MMU( The role of memory management unit )

** stay 32 Under the machine , The size of virtual memory space that a process can manage is 4G.** In fact, the size of physical space is not 4G. The correspondence and management of physical memory and virtual memory is through MMU And address translation record table .

image-20220705021709810

For example .data Stored in a=10, Then you can pass MMU( The mapping relationship between virtual memory and physical memory is recorded ), Convert his virtual address to physical address , To access content 10.

Memory access level :

  • 0 It's the highest level , Permissions for kernel access

  • 3 It is the permission that allows users to access the permission level

Mapping problem :

  • User space mapping to physical space memory is independent ( Different processes , Even if the virtual address is the same , Corresponding to different physical spaces )

  • The memory mapped from kernel space to physical space is the same .( Above picture , Two processes kernal Points to the same block with permission 0 Of MMU)

1.3.4PCB( Process control block ) The understanding of

Each process has a process control block in the kernel PCB( Pictured above ) To maintain process related information , stay linux The process control block of the lower kernel is struct task_struct Structure .

task_struct Key member resolution of :

  • process id, Each process in the system has a unique id, Use... In a structure pid_t Type said , It is essentially a nonnegative integer .( Facilitate process management )
  • State of process : be ready , function , Hang up , stop it
  • Process switch need to save and restore some of the CPU register
  • Information describing the virtual address space
  • Describe the information of the control terminal
  • Current working directory
  • umask Mask
  • Document descriptor table , Contains a lot of points to file Pointer to structure
  • Information related to signals
  • user id And groups id
  • Sessions and process groups
  • The maximum number of resources a process can use
1.3.5 Get environment variables
env  # Get all environment variables 
# Common environment variables :PATH,SHELL,TERM,LANG,HOME

PATH: Search path for executable 
SHELL: Show the current SHELL
echo $TERM: Current terminal type , Under the graphical interface terminal, the value is usually xterm,
echo $LANG: Language and locale, Determines the string encoding and time 、 Display format of currency and other information 
echo $HOME: The home directory path of the current user , Many programs need to save configuration files in their home directory , So that each user has his own set of configuration when executing the program .

getenv Get environment variable function

// Get environment variables 
char* getenv(const char* name);
/*  success : Returns the value of the environment variable , Failure : return NULL */

mygetenv.c
int main(){
    
    const char*s="PATH";
    char*print=getenv(s);
    prinf("%s\n",print);
    return 0;
}
gcc mygetenv.c
./a.out
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

setenv Set the environment variable function

int setenv(const char*name,const char*value,int overwrite);
/*  Parameters overwrite Value : 1. Overwrite the original environment variables  0. No coverage , It is often used to set new environment variables  */

/*  Add environment variables using instructions  key Is the environment variable type ,value Value the environment variable  */
export key=value  

unsetenv Delete environment variable function

int unsetenv(const char*name);
/*  success :0  Failure :-1 name non-existent :0 */

2. Control process

2.1 Process control functions fork

fork() Function creates a process that is almost identical to the original process through system call , That is, two processes can do exactly the same thing , But if the initial parameters or the variables passed in are different , Two processes can also do different things .

#include<unistd.h>
pid_t fork(void);
/* pid_t It's a process ID  Failure : return -1  Return value , success : There are two returns ; The parent process returns the ID  Subprocess return 0; */

// Process get function 
#include<sys/types.h>
#include<unistd.h>
// Get the current process of ID
pid_t getpid(void);
// Get the parent process of the current process ID
pid_t getppid(void);

image-20220705144326880

#include<stdio.h>
#include<unistd.h>
int main(){
    
    printf("begin.....\n");
    pid_t pid=fork();
    printf("end.......\n");
    return 0;
}

image-20220705145934709

printf(“end…\n”); Twice , Statement fork() There is only one process before execution ,fork() Two processes appear after execution .

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>

int main(){
    
    printf("begin()...\n");
    pid_t pid=fork();
    // If it is less than 0, Indicates that the process failed to open 
    if(pid<0){
    
        perror("fork err");
        exit(-1);
    }
    if(pid==0){
    
        printf("I am child pid,pid=%d,ppid=%d",getpid(),getppid());
    }
    else if(pid>0){
    
        printf("I am father pid,pid=%d,child=%d,ppid=%d",getpid(),pid,getppid());
    }
    printf("end......\n");
    return 0;
}

image-20220705153903166

/*  explain pid Why is the value of different in the parent-child process .  In fact, it is equivalent to a linked list , Processes form a linked list , Parent process pid(p meaning point) The process that points to the child process id,  Because the child process has no child process , So its pid by 0. This also explains why the parent process fork Returned by subprocess id, The subprocess returns 0;  It can be proved that : Observe the parent-child process above id, Parent process id Just less than child processes 1 */

analysis :

Process from fork() After the function is executed, it starts to become two processes , stay linux Next , The child process and the parent process are concurrent . Of course, we should let the subprocess end first , Then the parent process ends , Otherwise, it will appear Orphan process .

int main(){
    
    printf("begin()...\n");
    pid_t pid=fork();
    // If it is less than 0, Indicates that the process failed to open 
    if(pid<0){
    
        perror("fork err");
        exit(-1);
    }
    if(pid==0){
    
        printf("I am child pid,pid=%d,ppid=%d",getpid(),getppid());
    }
    else if(pid>0){
    
        printf("I am father pid,pid=%d,child=%d,ppid=%d",getpid(),pid,getppid());
        sleep(1);
    }
    printf("end......\n");
    return 0;
}

image-20220705154653774

Delay the end time of the parent process , Let the subprocess end first .

2.1.2fork() Function advanced
// First look at a code 
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main(void)  
{
      
   int i=0;  
   printf("i son/pa ppid pid cpid\n");  
   //ppid Refers to the parent process of the current process pid 
   //pid Refers to the current process pid, 
   //fpid finger fork The value returned to the current process  
   for(i=0;i<2;i++){
      
       pid_t cpid=fork();  
       if(fpid==0)  
           printf("%d child %4d %4d %4d\n",i,getppid(),getpid(),cpid);  
       else  
           printf("%d parent %4d %4d %4d\n",i,getppid(),getpid(),cpid);  
   }  
   return 0;  
}  

image-20220705164717139

Execution order

image-20220705171143904

 for        i=0         1           
              father     father     
                                      
                            son     
                                  
               son       father 
                                 
                            son     
// The question is how many processes are created in each of the following processes ( remove main process )
#include <stdio.h> 
#include <unistd.h> 
int main(int argc, char* argv[])  
{
      
   fork();  
   fork() && fork() || fork();  
   fork();  
   return 0;  
}
// Altogether 20 A process , remove main also 19 A process .
A&&B, If A=0, There is no need to continue &&B 了 ;A Not 0, You need to continue &&B
A||B, If A Not 0, There is no need to continue ||B 了 ,A=0, You need to continue ||B.

image-20220705172409738

2.2 Process command control

int main(){
    
    printf("begin()...\n");
    pid_t pid=fork();
    // If it is less than 0, Indicates that the process failed to open 
    if(pid<0){
    
        perror("fork err");
        exit(-1);
    }
    if(pid==0){
    
        printf("I am child pid,pid=%d,ppid=%d",getpid(),getppid());
        while(1){
    
            printf("I am child\n");
                sleep(1);
        }
        
    }
    else if(pid>0){
    
        printf("I am father pid,pid=%d,child=%d,ppid=%d",getpid(),pid,getppid());
        while(1){
    
            printf("I am father\n");
        	sleep(1);
        }
    }
    printf("end......\n");
    return 0;
}

image-20220705173140201

It can be seen that the child process and the parent process are concurrent ;

ps aux   # View process information 
ps ajx   # Check the blood relationship between processes 
kill  -9  pid    # Kill process ID by pid The process of  -9 Force kill process 

image-20220705174439292

kill -9 11549

image-20220705174523925

2.3 establish n A process

Let the parent process create multiple child processes

int main(){
    
    int n=5;
    int i=0;
    pid_t pid=0;
    for(i;i<n;i++){
    
        pid=fork();
        if(pid==0){
    
            printf("I am child,pid=%d,ppid=%d",getpid(),getppid());
            break;// The subprocess jumps out of the loop , No longer create child processes 
        }
        else{
    
            printf("I am father,pid=%d,ppid=%d",getpid(),getppid());
        }
    }
    // Ensure that the process will not die 
    while(1){
    
        sleep(1);
    }
}
2.4 Loop creation n Subprocesses control order
// To exit the process in sequence ,main The process finally exited 
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main(){
    
    int n=5;
    int i=0;
    pid_t pid=0;
    for(i;i<n;i++){
    
        pid=fork();
        if(pid==0){
    
            // Different sub processes i The value is different. ,main The final value of the process is n
            printf("I am child%d,pid=%d,ppid=%d",i,getpid(),getppid());
            break;// The subprocess jumps out of the loop , No longer create child processes 
        }
        else if(pid>0){
    
            printf("I am father%d,pid=%d,ppid=%d",i,getpid(),getppid());
        }
    }
    // adopt i Control the sleep length and turn off the process in sequence 
    sleep(i);
    if(i<n){
    
        printf("I am child%d,will exit,pid=%d\n",i,getpid());
    }else{
    
        printf("I am father,will exit,pid=%d\n",getpid());
    }
    return 0;
}

image-20220705212605101

3. Father child process

3.1 What parent-child processes can share

Look at the code below

int main(int argc,char*argv){
    
    printf("begin......");
    fork();
    printf("end........\n");
    return 0;
}

image-20220705214020742

begin… No, \n Therefore, it is stored in the buffer .fork() The previous content belongs to the shared area , therefore end…\n Line feed flush buffer , So print out two lines begin…end…

Process sharing

Between father and son processes fork() After the fork , Similarities and differences .

Just. fork after :

Father and son are alike : Global variables ,.data Area ,.text Area , Stack , Pile up , environment variable (0-3G User space ), user ID, Host Directory , Process working directory , Signal processing mode …

Father and son are different :1. process ID,2.fork Return value ,3. The parent process id,4. Process run time ,5. alarm clock ( Timer ),6. Pending signal set

Child process and parent process 0-3G The user space content of is the same , And copied the parent process PCB, however pid Different .

But the child process is not copying the parent process 0-3G User space , The parent-child processes meet Share on read copy on write Principles , So as to reduce the cost of space .

image-20220705221021113

 int var=100; 
 int main()
 {
    
  	pid_t pid=fork();
     if(pid==0){
    
     printf("var=%d,child,pid=%d\n",var,getpid());
     var=1001;
     printf("var=%d,child,pid=%d\n",var,getpid());
     sleep(2);
    printf("var=%d,child,pid=%d\n",var,getpid());
  }else{
    
     sleep(1);
     printf("var=%d,parent,pid=%d\n",var,getpid());
     var=1002;
     sleep(5)
      printf("var=%d,parent,pid=%d\n",var,getpid());   
   }                                   
   return 0;                           
 }

image-20220705222845023

It can be seen that , The parent and child processes modify the values of global variables respectively, which does not affect each other , Description: it meets the requirements of share on read and copy on write .

3.2exec Process execution family functions

#include <unistd.h>
extern char **environ;
// Other programs are embedded and executed in the middle of the program 
int execl(const char *path, const char *arg, ...);
// When executing the program , Use PATH environment variable , The executed program can be executed without adding a path 
int execlp(const char *file, const char *arg, ...);
/*  Return value : It's just happening err Will return the value   Parameter interpretation : path/file: File name or path  arg: Variable parameter list   The parameter list needs NULL ending , As a sentinel   Execution principle : The .text,.data Replace with the program you want to load .text,.data, And then let the process start again .text. The first instruction of starts execution . */

example

int main(){
    
    execlp("ls","ls","-l",NULL);
    execl("/bin/ls","ls","-l",NULL)
/*  Parameter interpretation :  first ls For the file name   the second ls Is the first parameter in the variable parameter list , Keep consistent with the previous file name for placeholder . The last digit of the parameter list should be NULL */
    perror("exec err");
    return 0;
}

Execution results

image-20220705230102402

3.3 Orphans and zombie process

Orphan process : The child process at the end of the father process , The parent process of the child process is init process

Zombie process : End of subprocess , The parent process did not recycle the resources of the child process ( Process management block PCB);

#include<unistd.h>
// Orphan process 
int main(){
    
    // Returns the ID
    pid_t pid=fork();
    if(pid==0){
    
        printf("I am child,pid=%d\n",getpid());
        while(1){
    
            sleep(1);
        }
    }else{
    
        printf("I am parent,pid=%d\n",getpid());
        printf("parent end.....\n")
    }
    return 0;
}

// Zombie process , There is no recycling of resources for child processes 
int main(){
    
    // Returns the ID
    pid_t pid=fork();
    if(pid==0){
    
        printf("I am child,pid=%d\n",getpid());
    }
	else{
    
        while(1){
    
            printf("I am father,pid=%d",getpid());
            sleep(1);
        }
    }
    return 0;
}

Zombie processes cannot use kill Order clear , because kill The command is only used to terminate the process , And the zombie process has ended , Just no recycling .

3.4wait Recycling subprocess functions

#include <sys/types.h>
#include <sys/wait.h>
/*  Function function : 1. The blocking waiting process dies  2. Reclaim child process resources  3. Investigate the cause of death of the subprocess  */
pid_t wait(int *status);
/*  Parameter description : status It's an outgoing parameter , You can get the cause of process death   Return value :  success : Returns the of the recycling subprocess ID  Failure : return -1 */
int main(){
    
    pid_t pid=fork();
    if(pid==0){
    
        printf("I am child,will die,pid=%d\n",getpid());
        sleep(3);
    }else if(pid>0){
    
        printf("I am parent,waiting for child die,pid=%d\n",getpid());
        // Blocking waits for the child process to die 
        pid_t wpid=wait(NULL);
        printf("pid=%d die",wpid);
    }
    return 0;
}

Output

I am parent,waiting for child die,pid=23746
I am child,will die,pid=23747
# The parent process is blocked , Wait for the subprocess to die before proceeding to the next program 
pid=23747 die

3.5 Get the cause of death of the process

/*  Cause of process death : WIFEXITED(status)  If WIFEXITED It's true , That is, normal death exit . Use WEXITSTATUS(status) Get the exit status . WIFSIGNALED(status)  If WIFSIGNALED It's true , That is, abnormal death ( Killed by a signal ), Use WTERMSIG(status) Get the signal  */
int main(){
    
    pid_t pid=fork();
    if(pid==0){
    
        printf("I am child,will die,pid=%d\n",getpid());
        sleep(3);
        return 101;
    }
    else if(pid>0){
    
        printf("I am parent,waiting for child die,pid=%d\n",getpid());
        // Blocking waits for the child process to die 
        int status;
        pid_t wpid=wait(&status);
		if(WIFEXITED(status)){
    
            printf("child exit with %d\n",WIFEXITED(status));
        }
        if(WIFSIGNALED(status)){
    
            printf("child killed by %d\n",WTERMSIG(status));
        }
        printf("pid=%d die",wpid);
    }
    return 0;
}

3.6waitpid Recycling subprocess functions

pid_t waitpid(pid_t pid, int *status, int options);
/*  Parameters options: WNOHANG: If the child process is still alive, return immediately ( Not blocking waiting ) WUNTRACED: Pause state  0 and wait identical , Blocking and waiting will occur   Parameters pid: < -1  If a process group ID by pid, Pass in -pid The process group can be recycled  -1  Recycle all arbitrary processes  0  Recycle and call process groups ID Child processes in the same group  > 0  Recycling ID by pid The process of   Return value :  If set WNOHANG, So if no child process exits , return 0  If there is , Return to child process pid  Return if failed -1  other : Failure to return -1  success : Return to child process pid */

int main(){
    
    pid_t pid=fork();
    if(pid==0){
    
        printf("I am child ,pid=%d\n",getpid());
        sleep(2);
    }
    else if(pid>0){
    
        printf("I am parent,pid=%d\n",getpid());
        // Reclaim any child process , If the process does not die , Just go back to 0; If there is , Back to the process ID
        int ret=0;
        while(ret==0)
        {
    
        	ret=waitpid(-1,NULL,WNOHANG);
        	printf("ret=%d\n",ret);
        }
        if(ret<0){
    
            perror("wait err");
        }
        printf("child die,child=%d",pid);
    }
    return 0;
}

image-20220706012352853

3.6.1 Recycle multiple child processes

wait Function recycling subprocess

// use wait Recycle subprocess 
int main(){
    
    int n=5;
    int i=0;
   	pid_t pid;
    for(;i<n;i++){
    
        pid=fork();
        // Avoid child processes from generating grandchildren 
        if(pid==0){
    
            break;
        }
        else if(pid>0){
    
            printf("I am child,pid=%d\n",getpid());
        }
    }
    // Expand processes in order 
    sleep(i);
    // If it is main process , Just recycle the subprocess 
    if(i==5){
    
        //wait Recycling n Secondary subprocess 
        for(i=0;i<n;i++){
    
            pid_t wpid=wit(NULL);
            printf("child=%d, Recycling \n",wpid);
        }
    }
    return 0;
}

image-20220706014234399

waitpid Recycle subprocess

int main(){
    
    int n=5;
    int i=0;
   	pid_t pid;
    for(;i<n;i++){
    
        pid=fork();
        // Avoid child processes from generating grandchildren 
        if(pid==0){
    
            break;
        }
    }
    sleep(i);
    // If it is main process , Just recycle the subprocess 
    if(i==5){
    
        int ret=0;
        while(1){
    
            ret=waitpid(-1,NULL,WNOHANG);
            if(ret>0){
    
                printf("child=%d Recycling \n",ret);
            }
            else if(ret==-1)
            {
    
                break;
            }
        }
    }
    if(i<n){
    
        printf("I am child,pid=%d\n",getpid());
    }
    return 0;
}

image-20220706015037142

原网站

版权声明
本文为[People in the shadow LX]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/188/202207070339226343.html