The process of Linux system programming (Linux process, fork() function, zombie process, orphan process)

1.Linux process

1.1 Process concept:

  • From the user's point of view: a process is a running program.
  • Operating system perspective: The operating system runs a program and needs to describe the running process of the program. This description is described by a structure task_struct{}, collectively referred to as PCB, so for the operating system, the process is PCB (process control block) program control Piece
  • The description information of the process includes: identifier PID, process status, priority, program counter, context data, memory pointer, IO status information, and accounting information. All need the operating system for scheduling.

1.2 Process status:

/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char * const task_state_array[] = {
    
    
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};

2.fork() function

2.1 Overview:

The child process obtained by using the fork() function is a copy of the parent process. It inherits the address space of the entire process from the parent process:
including process context (static description of the entire process of process execution activities), process stack, and open files Descriptors, signal control settings, process priority, process group number, etc. The only thing unique to the child process is its process number, timer, etc. (only a small amount of information).

pid_t fork(void);

head File:

#include <sys/types.h>
#include <unistd.h>

Features:

  • Used to create a new process from an existing process, the new process is called the child process, and the original process is called the parent process.

return value:

  • Success: 0 is returned in the child process, and the child process ID is returned in the parent process. pid_t is an unsigned integer.
  • Failure: return -1.

Code example:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
 
int main(int argc, char *argv[])
{
    
    
	pid_t pid;
	pid = fork();
	
	if( pid < 0 ){
    
    	// 没有创建成功
		perror("fork");
	}
	
	if(0 == pid){
    
     // 子进程
		while(1){
    
    
			printf("I am son\n");
			sleep(1);
		}
	}
	else if(pid > 0){
    
     // 父进程
		while(1){
    
    
			printf("I am father\n");
			sleep(1);
		}
	}
	
	return 0;
}

2.2 Operation results:

Insert picture description here

2.3 Summary:

  • Through the running results, you can see that the parent and child processes each do one thing (each one prints a sentence). Here, we only see that there is only one piece of code. In fact,
    after fork() , two address spaces are running independently, which is a bit similar to having two independent programs (parent and child processes) running. It should be noted that in the address space of the child process, the child process starts executing code after the fork() function.
  • After fork(), it is uncertain whether the parent process executes first or the child process executes first. This depends on the scheduling algorithm used by the kernel.

3. Zombie process

A process uses fork to create a child process. If the child process exits and the parent process does not call wait() or waitpid() to obtain the child process information, then the child process descriptor is still stored in the system, and this kind of process is called a zombie process.

Z 进程

3.1 The code simulates the zombie process:

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

int main()
{
    
    
  printf("输入一遍\n");
  pid_t ret = fork();
  if(ret > 0)
  {
    
    
    //parent    
    while(1)    
    {
    
        
    printf("I am parent! pid is : %d\n", getpid());    
    sleep(1);    
    }    
  }    
  else if(ret == 0)    
  {
    
        
    /child    
    int count = 0;    
    while(count<5)    
    {
    
        
      printf("I am child! pid is : %d, ppid: %d\n", getpid(), getppid());    
      count++;    
      sleep(2);    
    }    
    exit(0);    
  }    
  else    
  {
    
        
    printf("fork error\n");    
  }    
  sleep(1);    
  return 0;    
}

3.2 Display of the results of the zombie process:

Insert picture description here

3.3 Zombie process harm:

The exit status of the child process will always be maintained. Maintaining the exit status itself requires data maintenance. It also belongs to the basic information of the process and is stored in task_structit. That is to say, as long as the Z state does not exit, the PCB must maintain the exit information. If a parent process creates many child processes without recycling, it will 造成内存资源的极大浪费and will cause it 内存泄露.

4. Orphan process

When the parent process exits early, the child process is called an "orphan process". Once the parent process exits, the child process is in the Z state when it wants to exit. Because no process receives its exit information, the orphan process must be adopted and recycled by the init process No. 1 to prevent the child process from becoming a zombie process.

4.1 The code simulates the orphan process:

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

int main()
{
    
    
  pid_t ret = fork();
  if(ret < 0)
  {
    
    
    printf("创建进程失败!\n");
  }
  else if(ret > 0)
  {
    
    
    int count = 0;
    while(count++ < 5)
    {
    
    
      printf("我是父进程(id:%d)\n",getpid());
      sleep(2);
    }
    exit(0);
  }
  else
  {
    
    
    while(1)
    {
    
    
      printf("我是子进程(id:%d)\n",getpid());
      sleep(1);
    }
  }
  sleep(1);
  return 0;
}

4.2 Display of the results of the orphan process:

Insert picture description here

4.3 Summary:

OS considers this situation, when the parent process exits and the child process is still running (the child process is called an orphan process), it finds a father for him again, as shown in the figure is process systemd No. 1.

Process No. 1 (init) extension:

Created by 0 process, complete the initialization of the system. It is the ancestor process of all other user processes in the system.
All processes in Linux are created and run by the init process. First, the Linux kernel is started, then the init process is started in the user space, and then other system processes are started. After the system startup is complete, init will become a daemon to monitor other processes in the system.

Guess you like

Origin blog.csdn.net/weixin_45313447/article/details/114443655