Process (on) - process creation, termination, and waiting code implementation process

Create a process
1. Fork function

The fork function is very important. The function function is to create a new process from an existing process, the newly created process is a child process, and the original process is a parent process.

#include<unistd.h>
pid_t fork(void);
//返回值:子进程中返回0,父进程返回子进程id,出错返回-1
  • Allocate new memory blocks and kernel data structures to child processes

  • Copy the contents of part of the data structure of the parent process to the child process

  • Add child process to system process list

  • fork() returns, start scheduler scheduling

2. Code implementation

write picture description here
run:
write picture description here

Note:
Before printing once and After twice, the reason is that the parent process executes independently before fork, and after fork, the two execution streams of parent and child are executed separately, and who executes first after fork is determined by the operating system scheduler.
Fork function, the child process returns 0, and the parent process returns the pid of the child process.

3. Fork usage
  • The parent process wants to copy itself, so that the parent and child processes execute different code segments at the same time, for example: the parent process waits for the client request, and the child process processes the request;

  • A process executes different programs, for example: after the child process returns from fork, the exec function is called.

The reason for the failure of the fork call:
too many processes in the system and insufficient
memory

4. vfork function

vfork is also used to create child processes

vfork is used to create a child process, and the child process and the parent process share the address space, that is, the shared virtual address space, the child process of fork has an independent address space

vfork ensures that the child process runs first, the parent process hangs, and the parent process does not execute until the child process ends. Only after calling exec or exit can the parent process be scheduled to run.

ps is equivalent to the task manager, reading information from pcb
ps -aux getpid/getppid

5. Code implementation

write picture description here
operation result:
write picture description here


The second process terminates
1. Process exit scenario
  • The code runs and the result is correct

  • The code finishes running and the result is incorrect

  • Abnormal exit
    (often exiting because of receiving a signal)

2, the method of process exit
  • Normal termination
    1, return from main
    2, call exit
    3, _exit

  • Abnormal termination
    ctrl + c, signal terminated

3. _exit function
#include<unistd.h>
void _exit(int status);
//参数:status定义了进程终止状态,父进程通过wait来获取该值

Although status is of type int, only the lower eight bits are used by the parent process, so when _exit(-1), execute $? at the terminal and find that the return value is 255.

4. exit function
#incldue<unistd.h>
void exit(int status);

Executing exit(n) is equivalent to return(n), because the run function that calls main uses the return value of main as an argument to exit.

Three processes waiting
1. Why do processes wait
  • If the child process exits and the parent process ignores it, it may cause the problem of zombie process and then memory leak.

  • Once the process becomes a zombie process, kill -9 can't do anything

  • The result of the completion of the task assigned by the parent process to the child process

  • The parent process recycles the resources of the child process and obtains the exit information of the child process by means of process waiting.

2. The wait method waits
#include<sys/types.h>
#incldue<sys/wait.h>
pid_t wait(int *status)
//返回值:
//成功返回被等待的进程PID,失败返回-1。
//父进程有多个子进程,只有返回PID,才能准确知道是哪个子进程。

//参数:
//输出型参数,获取子进程退出状态,不关心可以设置成NULL

Once the process calls wait, it blocks itself immediately, and wait automatically analyzes whether a sub-process of the current process has exited. If it finds such a sub-process that has become a zombie, wait will collect the information of the sub-process. And destroy it completely and return; if no such child process is found, wait will block here until one appears.

3. waitpid method
pid_t waitpid(pid_t pid,int *status,int options);

In essence, the functions of the system calls waitpid and wait are exactly the same, but waitpid has two more parameters pid and options that can be controlled by the user, thus providing us with another more flexible way of programming. Let's take a closer look at these two parameters:

pid: As can be seen from the parameter name pid and type pid_t, what is needed here is a process ID. But it has a different meaning here when pid takes different values.

     pid>0时,只等待进程ID等于pid的子进程,不管其它已经有多少子进程运行结束退出了,只要指定的子进程还没有结束,waitpid就会一直等下去。

     pid=-1时,等待任何一个子进程退出,没有任何限制,此时waitpid和wait的作用一模一样。

     pid=0时,等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid不会对它做任何理睬。

     pid<-1时,等待一个指定进程组中的任何子进程,这个进程组的ID等于pid的绝对值。

options: options provides some additional options to control waitpid. Currently, only two options, WNOHANG and WUNTRACED, are supported in Linux. These are two constants that can be used by concatenating them with the "|" operator, for example:

ret=waitpid(-1,NULL,WNOHANG | WUNTRACED);

If we don't want to use them, we can also set options to 0, for example:

ret=waitpid(-1,NULL,0);

If waitpid is called with the WNOHANG parameter, it will return immediately even if no child process exits, instead of waiting forever like wait.

As for the WUNTRACED parameter, because it involves some knowledge of tracking and debugging, and it is rarely used, there is no need to spend more time here. Interested readers can refer to the relevant materials by themselves.

Seeing this, smart readers may have seen the clue: isn't wait the packaged waitpid? Yes, looking at lines 349-352 of the <kernel source directory>/include/unistd.h file, you will find the following program segment:

static inline pid_t wait(int * wait_stat)

{

    return waitpid(-1,wait_stat,0);

}

return value and error

The return value of waitpid is slightly more complicated than wait, and there are three cases:

      1、当正常返回的时候,waitpid返回收集到的子进程的进程ID;

      2、如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;

      3、如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;

When the child process indicated by pid does not exist, or the process exists but is not a child process of the calling process, waitpid will return with an error, and errno is set to ECHILD.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325728623&siteId=291194637