Linux: Detailed explanation of process creation

Process creation

Now that we know the concept of a process and how to create a process, let's explore the details of process creation in detail.

1.fork function

In Linux, the fork function can create a new process from an existing process, the new process is the child process, and the original process is the parent process

#include <unistd.h> //头文件

pid_t = fork(void);
//返回值有三种情况
//pid_t = 0 表示子进程
//pid_t > 0 表示父进程
//pid_t < 0 表示创建失败

The process calls the fork function. When control is transferred to the fork code in the kernel, what the kernel needs to do is:
1. Allocate a new memory block and kernel data structure to the child process
2. Copy part of the data structure content of the parent process to the child process
3. Add the child process to the system process list.
4. Fork returns. Start the scheduler scheduling
The main idea of ​​creating a child process by calling fork is to create a child process by copying the parent process (copying the data in the parent process pcb), the code is shared but the data is unique.
Insert picture description here

int main( void )
{
    
    
 pid_t pid;
 printf("Before: pid is %d\n", getpid());
 if ( (pid=fork()) == -1 )perror("fork()"),exit(1);
 printf("After:pid is %d, fork return %d\n", getpid(), pid);
 sleep(1);
 return 0;
}

Insert picture description hereThere are three lines of output, one line before and two lines after. Process 3255 prints the before message first, and then it prints after. Another after message has 3256 printed. Note that the process 3256 did not print before, the reason is shown in the figure belowInsert picture description here

Copy-on-write

Copy-on-write is a technology that can delay or even dispense with copying data. The kernel does not copy the entire process address space at this time, but allows the parent process and the child process to share the same copy. Copy-on-write, data will be copied only when it is written, so that each process has its own copy, that is, the copy of resources is only performed when it needs to be written. Before that, only with Read-only sharing. To put it simply: Normally, the code is shared between the father and the son. When the father and son do not write, the data is also shared. When either party tries to write, a copy of each is done by copy-on-write.
Insert picture description here

The reason for the call failure

(1). There are too many processes in the system
(2). The number of processes of the actual user exceeds the limit

2.vfork function

The function of vfork() is the same as fork(), the difference is that vfork() does not copy the page table entries of the parent process. When a process is created in this way, the child process runs in its address space as a separate thread of the parent process, and the parent process is blocked, which means that only when the child process exits, the parent process can continue to execute, and the child process Cannot write to the address space. The advantage of using vfork is that there is no need to copy the page table entries of the parent process. (Note: With the advent of copy-on-write technology, vfork is generally no longer used)

Process termination

It is the exit of the process. Generally speaking, there are two situations: normal exit and abnormal exit.
Normal exit: The process exits where the process runs to return or exit, that is, it exits where we let it exit.
Abnormal exit: The task is not completed, and the program exits for some reason when it runs halfway through.

Three ways to exit normally

(1) _exit function
Call void exit (int status) at any position; you can exit a process at any position in the program

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

Note: Although the status is int, only the lower 8 bits can be used by the parent process. So when _exit(-1), execute $? in the terminal and find that the return value is 255
(2). exit function
Call void _exit(int status) at any position; you can exit a process at any position in the program

#include <unistd.h>
void exit(int status);

(3)
. return exits the return in the main function; (return in the ordinary function can only exit the function, not the process), return is a more common method of exiting the process. Executing return n is equivalent to executing exit(n), because the runtime function of calling main will take the return value of main as the parameter of exit.

The difference between _exit and exit

Calling void exit (int status/void _exit (int status) at any position, you can exit a process at any point in the program, but when the former exits the process, the buffer is refreshed and the data in the buffer is written to the data, while the latter When exiting the process, the resources are released directly without refreshing the buffer; exit is a library function, and _exit is a system call interface

Guess you like

Origin blog.csdn.net/qq_43825377/article/details/113817840