C/C++ process thread super detailed explanation

Table of contents

Preface

1. Process Basics

1. Process concept

2. Process characteristics

3. Process status (as clearly visible in the picture)

4. Process identification

The example code is as follows:

5. Types of processes

The example shell script program is as follows:

2. Process API

1. Create a child process

The example code is as follows:

2.exec function family

 The function family explanation diagram is as follows:

The example code is as follows: 

3. End the process

The example code is as follows:

4. Collect the corpse of the process (release the resources occupied by the process)

 The wait example code is as follows:

The waitpid example code is as follows: 

Summarize


Preface

What is the broad meaning of process and thread?

A process is an instance of a program running in a computer. It has independent memory space and resources and is the basic unit for the operating system to allocate and manage resources. Each process has its own independent address space, global variables, file opening and other resources, and the processes are independent of each other. Data exchange between processes usually occurs through the inter-process communication (IPC) mechanism.

A thread is an execution unit in a process. A process can contain multiple threads, which share the process's address space and resources and can execute different code paths simultaneously. Data can be exchanged between threads through shared memory because they have access to the same global variables and heap memory.


1. Process Basics

1. Process concept

A process is an independent schedulable task
    (1) A process is an abstract entity. When the system executes a program, various resources are allocated and released
    (2) A process is a process of executing a program at one time.
The difference between a process and a program
    is that a program is static. It is an ordered sequence of instructions stored on the disk. Collection, without any concept of execution.
    Process is a dynamic concept. It is the process of program execution, including creation, scheduling and death.
    Process is the smallest unit of program execution and resource management.

2. Process characteristics

Dynamics - the process of running a program at one time
Concurrency - multiple processes can be run at the same time
Independence - each process runs in its own independent virtual memory
Asynchronous - multiple running processes There is no relationship between them

3. Process status (as clearly visible in the picture)

4. Process identification

(1) Main process identification
    process number (Process Identity Number, PID)
    parent process number (Parent Process ID, PPID)
    
(2) PID uniquely identifies a process. It can be obtained through the following two functions:
    pid_t getpid(void) //Get the process ID
    pit_t getppid(void) //Get the parent process ID

The example code is as follows:

int main(void)
    {
        printf("pid = %d\n",getpid());
        printf("ppid = %d\n",getppid());
        return 0;
    }

 The results of running in the terminal and the results of the ps command are as follows:

5. Types of processes

(1) Interactive process:
    This type of process is controlled and run by the shell. Interactive processes can run in the foreground or in the background.
    
(2) Batch process:
    This type of process does not belong to a terminal. It is submitted to a queue for sequential execution.

The example shell script program is as follows:

        Enter the command in the terminal as follows:

        touch test.sh
        chmod a+x test.sh  
        test.sh content is as follows:
        ls
        touch 1.txt 2.txt 3.txt
        ls /
        cat fork1.c

 Run the shell script file as follows:

     peter@ubuntu:~/2308/proc/day01_code$ ./test.sh
     1.txt  3.txt   exit.c   fork2.c   main.c    myproc.c  test.sh  wait.c   waitpid.c
     2.txt  exec.c  fork1.c  getpid.c  Makefile  test.c    wait     waitpid
     bin   cdrom  etc   initrd.img      lib    lost+found  mnt  proc  run   snap  swapfile  tftpboot         u  sr  vmlinuz
     boot  dev    home  initrd.img.old  lib64  media       opt  root  sbin  srv   sys       tmp                 var    vmlinuz.old
     #include <stdio.h>
     #include <sys/types.h>
     #include <unistd.h>

     int main(void)
     {
         fork();
         printf("hello world\n");
         return 0;
      }

 (3) Daemon process:
          This type of process runs in the background. It usually starts executing when Linux starts and ends when the system shuts down.

2. Process API

1. Create a child process

pid_t fork(void);

The fork calling process:
    1. Map the new process virtual space, which is called a child process.
    2. Copy the data in each data segment of the parent process to the child process
    3. The parent and child processes share the code segment
    4. The fork() calling process returns two values:
                  The first value: returns the ID number of the child process to the parent process.
                  Second value: Return 0 to the child process.
           Call failure returns: -1
    5. Parent and child processes, the next statement called from fork() runs at the same time.   

The example code is as follows:

void fun(void)
    {
        int i;
        for(i = 0 ; i  < 7; i++){
            printf("我是子进程,我要好好学习\n");
            sleep(1);
        }
    }

    int main(void)
    {
        int i;
        pid_t pid;

        if((pid = fork()) < 0){
            perror("fork");
            exit(1);
        }else if(!pid)
            fun();
        else
            for(i = 0 ; i  < 7; i++){
                printf("我是父进程,我要努力赚钱\n");
                sleep(1);
            }
        return 0;
    }

2.exec function family

//Load another program and execute it in the process space
#include <unistd.h>
extern char **environ;

int execl(const char *path, const char *arg, ... /* (char  *) NULL */);
int execlp(const char *file, const char *arg,.../* (char  *) NULL */);
int execle(const char *path, const char *arg,../*, (char *) NULL,char * const envp[] */);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);

 The function family explanation diagram is as follows:

 

The example code is as follows: 

int main(void)
{
    int i;
    pid_t pid;

    if((pid = fork()) < 0){
        perror("fork");
        exit(1);
    }else if(!pid){   //子进程:执行另一个程序,如:ls
#if 0
        //execl("/bin/ls","ls","-l",NULL);
        //execlp("ls","ls","-l",NULL);
        char * arg[] = {"ls","-l",NULL};
        //execv("/bin/ls",arg);
        execvp("ls",arg);
#else
        //execl("/home/peter/2308/proc/day01_code/myproc","./myproc",NULL);
        char * env[] = {"name = peter","passwd = 123",NULL};
        //execle("/home/peter/2308/proc/day01_code/myproc","./myproc",NULL,env);
        char * arg[] = {"./myproc",NULL};
        execve("/home/peter/2308/proc/day01_code/myproc",arg,env);
#endif
    }else{   //父进程循环打印
        for(i = 0 ; ; i++){
            printf("我是父进程,我要努力赚钱\n");
            sleep(1);
        }
    }
    return 0;
}

3. End the process

The example code is as follows:

#include <stdlib.h>
void exit(int status);   //在结束进程之前,会先刷新缓冲,释放缓冲区,关闭打开的文件,然后再结束进程。

 #include <unistd.h>
 void _exit(int status);   //直接结束进程,不会刷新缓冲,释放缓冲区,关闭打开的文件
 //参数 ---status:  0-表示正常结束,非0-表示异常结束
 
 例如: 
 int main(void)
    {
        printf("hello world");

        //exit(1);     
        _exit(1);

        while(1);  
        return 0;     //在main函数中,执行return语句,return会调用exit()
    }

4. Collect the corpse of the process (release the resources occupied by the process)

(1) wait
    #include <sys/types.h>
    #include <sys/wait.h>
    //Function: Collect the corpse of any child process
     . If the child process does not end, the parent process will block until the child process ends.
     If the parent process has no child processes, the wait function returns immediately.               
    pid_t wait(int *wstatus);   
    //Parameters ----- Variable address to save the end status of the child process
    //Return value----Success: ID of the child process that collected the body, failure: -1
    

 The wait example code is as follows:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>


int main(void)
{
    int i;
    pid_t pid1,pid2;
    int status;

    if((pid1 = fork()) < 0){
	perror("fork");
	exit(1);
    }else if(!pid1){
	for(i = 0 ; i  < 7; i++){
	    printf("子进程1--pid = %d\n",getpid());
	    sleep(1);
	}
	exit(0);
    }
    if((pid2 = fork()) < 0){
	perror("fork");
	exit(1);
    }else if(!pid2){
	for(i = 0 ; i  < 3; i++){
	    printf("子进程2--pid = %d\n",getpid());
	    sleep(1);
	}
	exit(120);
    }
    if(wait(&status) < 0){
	perror("wait");
	exit(1);
    }
    printf("给子进程收完尸\n");
    printf("status = %d\n",WEXITSTATUS(status));
    return 0;
}

 (2) waitpid
    //Function: Collect corpses for the specified process
    pid_t waitpid(pid_t pid, int *wstatus, int options);
    //Parameter 1 ---pid:
                pid > 0 Collect corpses for the child process with process number pid
                pid = -1 Same as wait(), collect corpse pid for any child process
                = 0 Collect corpse pid for any child process in the same process group of the current process
                < -1 Collect corpse pid for any child process in the process group with process group ID |pid| Collect the corpse
    //Parameter 2 ----The variable address that saves the end status of the child process
    //Parameter 3 ----Option, usually 0

The waitpid example code is as follows: 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>


int main(void)
{
    int i;
    pid_t pid1,pid2;
    int status;

    if((pid1 = fork()) < 0){
	perror("fork");
	exit(1);
    }else if(!pid1){
	for(i = 0 ; i  < 7; i++){
	    printf("子进程1--pid = %d\n",getpid());
	    sleep(1);
	}
	exit(234);
    }
    if((pid2 = fork()) < 0){
	perror("fork");
	exit(1);
    }else if(!pid2){
	for(i = 0 ; i  < 3; i++){
	    printf("子进程2--pid = %d\n",getpid());
	    sleep(1);
	}
	exit(120);
    }
    if(waitpid(pid1,&status,0) < 0){
	perror("wait");
	exit(1);
    }
    printf("给子进程收完尸\n");
    printf("status = %d\n",WEXITSTATUS(status));
    return 0;
}


Summarize

      This article provides a very detailed explanation of process threads. I hope it can help everyone!

       In the future, I will show you more important basic knowledge about embedded and C language. Thank you for supporting Lazy King!

       I hope this blog can bring help to all my friends. Finally, friends who have been invited by Lazy King will leave your precious comments and attention. Thank you!

Guess you like

Origin blog.csdn.net/weixin_58070962/article/details/133323195