Applicable occasions and commonly used programming models for muduo library learning 01-fork function (multi-process)

Dongyang's study notes

1 fork() function

An existing process can call fork() to create a new process.

#include <unistd.h>
pid_t fork(void);

Return value : The child process returns 0, and the parent process returns the child process ID; if an error occurs, it returns -1

The new process created by fork() is called a child process. The fork() function is called once but returns twice: the return value of the child process is 0, and the return value of the parent process is the process ID of the newly created child process.

The reason for returning the process ID of the child process to the parent process is: because a process can have multiple child processes, but there is no function that allows a process to obtain the process IDs of all its child processes. Similarly the parent process returns a value of 0 is just the opposite reason, by getppid()get parent process ID, and 一个进程只能有一个父进程.

子进程和父进程继续执行fork调用之后的指令。The child process is a copy of the parent process. For example, the child process obtains the data space, heap, and stack of the parent process 副本.

Note: What the child process has is 副本. The parent process and the child process do not share these storage spaces, they share the text segment.

Since exec is often followed after fork(), many of them now implement 并不执行a parent process data segment, heap, and stack 完全副本. Instead, 写时复制(COW)technology is used. These (storage) areas are shared by the child process and the parent process, and the kernel changes their access permissions 只读.

An example of the fork function

It can be seen from the running results that the modification of the variable made by the child process does not affect the value of the variable in the parent process.

#include "apue.h"

int     globval = 6;
char    buf[] = "a write to stdout\n";

int
main(void)
{
     
     
    int    var = 0;
    pid_t  pid;

    var = 88;
    if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1)
    {
     
     
         err_sys("write error");
    }

    printf("before fork\n");   //we don't flush stdout
    if ((pid = fork()) < 0)
    {
     
     
         err_sys("fork error");
    }
    else if (pid == 0)    // 子进程返回0
    {
     
     
         globval++;
         var++;
    }
    else       // 父进程返回子进程ID
    {
     
     
         sleep(2);
    }

    printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globval, var);

    exit(0);
}

Operation result :
a write to stdout
before fork
pid = 8833, glob = 7, var = 89
pid = 8832, glob = 6, var = 88

In general, it is the parent process to be performed after the fork or the child process before execution is 不确定的, it depends on the scheduling algorithm used by the kernel. If the parent process and the child process are required to synchronize with each other, some form of synchronization is required 进程间通信.

File Sharing

When the standard output of the parent process is redirected, the standard output of the child process is also redirected. In fact, a feature of fork is that all file descriptors of the parent process are "copied" ( 不是真正的复制) to the child process. The parent process and the child process each have the same open descriptor共享同一个文件表项 .

Consider the following situation, a process has three different open files, standard input, output, and error. When returning from the fork, we have the following structure: The
Insert picture description here
important point is that the parent process and the child process share the same文件偏移量 .

If the parent and child processes write the same descriptor, they need to be controlled synchronously .
(1) The parent process waits for the child process to complete. When the child process terminates, update the offset of the corresponding descriptor
(2) The parent process and the child process execute different program segments. In this case, after fork, the parent and child processes each close the descriptors that they do not need to use. This method is often used by network service processes

Other sharing

In addition to opening the file, many other attributes of the parent process are also inherited by the child process.

  • Actual user ID, actual group ID, effective user ID, effective group ID
  • Affiliate group ID
  • Short-range group ID
  • Session id
  • Control terminal
  • Set user ID flag and set group ID flag
  • Current working directory
  • Root directory
  • File mode creation shield
  • Signal shielding and arrangement
  • Execution-time close flag for any open file descriptor
  • surroundings
  • Connected shared storage segment
  • Storage image
  • Resource limit

The difference between parent/child process

  • The return value of fork is different
  • Process ID is different
  • The values ​​of tms_utime, tms_stime, tms_cutime and tms_ustime of the child process are set to 0
  • The child process does not inherit the file lock set by the parent process
  • The unprocessed alarm of the child process is cleared
  • The unprocessed signal set of the child process is set to the empty set

fork use

Two reasons for fork failure:

  • There are already too many processes in the system
  • The process overview of this actual user ID exceeds the system limit

Two uses of fork:

  • One is that the parent process wants to copy itself, so that the parent process and the child process execute different code blocks at the same time. This is common in network service inheritance-the parent process waits for the client's service request. When this kind of request arrives, call fork, let the child process handle the request, and continue to wait for the next request.
  • A process needs to execute a different program. This pair shellis a common situation. In this case, the child process is called immediately after returning from forkexec

Guess you like

Origin blog.csdn.net/qq_22473333/article/details/113481494