Process control
Create process
fork
//Create child process pid_t fork(void); //Success: the parent process returns the PID of the child process, and the child process returns 0; Failure: Return - 1, set errno value
The parent-child process who preempts the CPU time slice will execute first
Global variables cannot be shared between parent and child processes, although the printed addresses are the same because they are virtual addresses
If the parent-child process only reads global variables, the parent-child process has only one copy in memory and belongs to sharing
If any process in the parent-child process modifies the variable, it will copy a copy in memory, then modify it on the copy, and map it back after modification
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/types.h> #include<unistd.h> int main() { printf("before fork,pid:[%d]\n",getpid()); //Create child process pid_t pid = fork(); if(pid<0) { perror("fork error"); return -1; } else if(pid>0) { printf("father:pid==[%d]\n",getpid()); sleep(1); } else if(pid==0) { printf("child:pid==[%d]\n",getpid()); } printf("after fork,pid:[%d]\n",getpid()); return 0; }
ps and kill
ps aux | grep "xxx" ps ajx | grep "xxx" //-a: (all) processes of all users in the current system //-u: View the process owner and other information //-x: Display processes without control terminal -- processes that cannot interact with users [input, output] //-j: List information related to job control kill -l //Check what signals the system has kill -9 pid //Kill a thread
getpid and getppid
//Get the PID of the current process pid_t getpid(void); //Get the PID of the parent process of the current process pid_t getppid(void);
Loop to create n child processes
//Loop to create n child processes #include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/types.h> #include<unistd.h> int main() { int i=0; for(i=0;i<3;i++) { //Create child process pid_t pid = fork(); if(pid<0) { perror("fork error"); return -1; } else if(pid>0) { printf("father:pid==[%d]\n",getpid()); sleep(1); } else if(pid==0) { printf("The first%d Child processes, child:pid==[%d]\n",i+1,getpid()); break; } } return 0; }
exec function family
Sometimes it is necessary to execute other commands or user-defined applications in a process. At this time, the functions in the exec function family are used
Generally, the method is to call fork in the parent process to create the first child process, and then call exec function in the child process
execl
int execl(const char *path, const char *arg, ... /* (char *) NULL */); //Path: the absolute path of the program to execute //Parameter arg: the required parameter of the program to be executed //arg: placeholder, usually write the name of the application //arg: the parameter of the command //After parameter writing: NULL //If it is successful, it will not return and the code behind the exec function will not be executed; If it fails, the code after execl will be executed, and the error reason can be printed with perror //execl function generally executes the program written by itself
execlp
int execlp(const char *file, const char *arg, .../* (char *) NULL */); //file: the name of the command to execute. Search for the command according to the PATH environment variable //arg: occupied //arg: the parameter of the command //After parameter writing: NULL //If it is successful, it will not return and the code behind the exec function will not be executed; If it fails, the code after exec will be executed, and the error reason can be printed with perror //The execlp function is generally used to execute the program or command of the system
//Can global variables be shared between parent and child processes #include<stdio.h> #include<string.h> #include<stdlib.h> #include<fcntl.h> #include<sys/types.h> #include<unistd.h> #include<sys/stat.h> int main() { //Create a child process pid_t pid=fork(); if(pid<0) { perror("fork error"); return -1; } else if(pid>0) { printf("father\n"); sleep(2); } else if(pid==0) { printf("child\n"); execl("./test","test","hello","dd",NULL); perror("execl error"); } return 0;s }
Process recycling
When a process exits, the process can recover its own user area resources, but cannot recover the PCB resources in the kernel space. Its parent process must call the wait or waitpid function to recover the child process, so as to avoid the waste of system resources
Orphan process
If parent process of the a child process has died and child process is still alive, process becomes an orphan process
In order to ensure that each process has a parent process, the orphan process will be adopted by the init process. The init process becomes the adoptive parent process of the orphan process. When the orphan process exits, the init process completes the recycling of the orphan process
Zombie process
If the child process dies and the parent process is still alive, but the parent process does not call the wait or waitpid function to recycle the child process, the child process becomes a zombie process
How to solve the zombie process
- Since the zombie process is a dead process, you cannot kill it with the kill command
- Zombie processes can be eliminated by killing their parent processes. After killing its parent process, the zombie process will be adopted by the init process, which will complete the recovery of the zombie process
Process recycling function
wait
pid_t wait(int *status); //Block and wait for the child process to exit //Reclaim child process residual resources //Get child process end status (exit reason) //Success: the ID of the child process cleaned up; Failed: - 1 (no child process) //Status parameter: exit status of child process -- outgoing parameter //Disabled (status): non-zero → the process ends normally //WEXITSTATUS(status): get the process exit status //Wifsignled (status): non-0 → abnormal termination of process //WTERMSIG(status): get the signal number of process termination
//The parent process calls the wait function to complete the recycling of the child process #include<stdio.h> #include<string.h> #include<stdlib.h> #include<fcntl.h> #include<sys/types.h> #include<unistd.h> #include<sys/stat.h> #include<sys/wait.h> int main() { pid_t pid=fork(); if(pid<0) { perror("fork error"); return -1; } else if(pid>0) { printf("father:pid=[%d],fpid=[%d]\n",getpid(),getppid()); int status; pid_t wpid=wait(&status); printf("wpid==[%d]\n",wpid); if(WIFEXITED(status))//Normal exit { printf("child normal exit,status==[%d]\n",WEXITSTATUS(status)); } else if(WIFSIGNALED(status))//Killed by the signal { printf("child killed by signal,signo==[%d]\n",WTERMSIG(status)); } } else if(pid==0) { printf("child:pid=[%d],fpid=[%d]\n",getpid(),getppid()); sleep(5); return 9; } return 0; }
waitpid
pid_t waitpid(pid_t pid, int *status, in options); //Same as wait function //pid: //pid = -1 wait for any child process. Equivalent to wait //PID > 0 waits for a child process whose process PID is equal to PID. //pid = 0 wait for any child process whose process group ID is the same as the current process, that is, any process in the same process group as the process calling waitpid() function //pid < - 1 waits for any child process whose group ID is equal to the absolute value of pid. (applicable to child processes in other groups) //Status: the exit status of the child process. The usage is the same as that of the wait function //options: set to WNOHANG, the function is non blocking, set to 0, the function is blocking //Function return value //>0: returns the recycled child process ID; //-1: No child process //=0: parameter 3 is WNOHANG and the child process is running