当前位置:网站首页>[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;
}
边栏推荐
- Abnova circulating tumor DNA whole blood isolation, genomic DNA extraction and analysis
- Sqlmap tutorial (IV) practical skills three: bypass the firewall
- 详解机器翻译任务中的BLEU
- Explain Bleu in machine translation task in detail
- JS decorator @decorator learning notes
- Software acceptance test
- Implementation of AVL tree
- Convolutional neural network -- understanding of pooling
- Flexible layout (II)
- Détailler le bleu dans les tâches de traduction automatique
猜你喜欢
外包干了四年,废了...
MIPS uclibc cross compile ffmpeg, support g711a encoding and decoding
Four goals for the construction of intelligent safety risk management and control platform for hazardous chemical enterprises in Chemical Industry Park
抽丝剥茧C语言(高阶)指针进阶练习
At the age of 20, I got the ByteDance offer on four sides, and I still can't believe it
我理想的软件测试人员发展状态
How to reduce inventory with high concurrency on the Internet
Summary of customer value model (RFM) technology for data analysis
How can brand e-commerce grow against the trend? See the future here!
Apache AB stress test
随机推荐
Detailed explanation of transform origin attribute
计算机服务中缺失MySQL服务
选择商品属性弹框从底部弹出动画效果
抽絲剝繭C語言(高階)指針的進階
机器人技术创新与实践旧版本大纲
Torefs API and toref API
At the age of 20, I got the ByteDance offer on four sides, and I still can't believe it
"Xiaodeng in operation and maintenance" meets the compliance requirements of gdpr
抽丝剥茧C语言(高阶)指针的进阶
Abnova immunohistochemical service solution
Select the product attribute pop-up box to pop up the animation effect from the bottom
Kuboard无法发送邮件和钉钉告警问题解决
考研失败,卷不进大厂,感觉没戏了
Composition API premise
外包干了三年,废了...
07_ Handout on the essence and practical skills of text measurement and geometric transformation
LC interview question 02.07 Linked list intersection & lc142 Circular linked list II
Flexible layout (I)
Reflection (II)
How do I get the last part of a string- How to get the last part of a string?