当前位置:网站首页>[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】
List of articles
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
1.3 Transition of process state
cpu and MMU( Memory management unit )
- Registers are the fastest
- Alu can only continue + The calculation and << operation
1.3.1 Process state switch
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 .
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);
#include<stdio.h>
#include<unistd.h>
int main(){
printf("begin.....\n");
pid_t pid=fork();
printf("end.......\n");
return 0;
}
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;
}
/* 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;
}
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;
}
Execution order
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.
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;
}
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
kill -9 11549
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;
}
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;
}
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 .
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;
}
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
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;
}
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;
}
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;
}
边栏推荐
- Composition API 前提
- Convolutional neural network -- understanding of pooling
- main函数在import语句中的特殊行为
- Stockage et pratique des données en langage C (haut niveau)
- 外包干了四年,废了...
- Modify the jupyter notebook file path
- "Xiaodeng in operation and maintenance" meets the compliance requirements of gdpr
- Implementation of AVL tree
- 记一个并发规则验证实现
- Role of virtual machine
猜你喜欢
How to model and simulate the target robot [mathematical / control significance]
1089: highest order of factorial
非父子组件的通信
抽絲剝繭C語言(高階)數據的儲存+練習
Precise space-time travel flow regulation system - ultra-high precision positioning system based on UWB
父组件传递给子组件:Props
异步组件和Suspense(真实开发中)
虚拟机的作用
Bindingexception exception (error reporting) processing
Asynchronous components and suspend (in real development)
随机推荐
Lm11 reconstruction of K-line and construction of timing trading strategy
深度学习花书+机器学习西瓜书电子版我找到了
詳解機器翻譯任務中的BLEU
Model application of time series analysis - stock price prediction
Abnova circulating tumor DNA whole blood isolation, genomic DNA extraction and analysis
Stack Title: nesting depth of valid parentheses
弹性布局(一)
Fast quantitative, abbkine protein quantitative kit BCA method is coming!
How to reduce inventory with high concurrency on the Internet
Multidisciplinary integration
点亮显示屏的几个重要步骤
JS small exercise
Communication between non parent and child components
sql中对集合进行非空校验
Stockage et pratique des données en langage C (haut niveau)
Fullgc problem analysis and solution summary
Calculus key and difficult points record part integral + trigonometric function integral
Abnova membrane protein lipoprotein technology and category display
Cloud backup project
Differences between H5 architecture and native architecture