Golang(Go语言)中实现典型的fork调用

Golang(Go语言)中实现典型的fork调用

原文见:https://jiajunhuang.com/articles/2018_03_08-golang_fork.md.html

背景

在日常的系统编程中,我们经常有这样的需求:fork 多个子进程去执行任务。例如典型的 master-slave 架构便是这样的,fork 调用之后,父进程开始作为管理进程管理子进程,而子进程则开始执行处理请求的代码。但是在Go语言中,由于Go语言屏蔽了进程、线程的概念,而只提供了 goroutine 的概念,导致我们无法很好的直接操作 fork 调用。在Go语言中,此类解决方案只有以下三种:

  • syscall.ForkExec
  • os.StartProcess
  • exec.Cmd

这三个都类似于 fork + exec,但是没有类似C中的fork调用可以达到在fork之后根据返回的pid然后进入不同的函数的方案。原因主要是:

  • fork 早出现在只有进程,没有线程的年代
  • C中是自行控制线程,这样fork之后才不会发生紊乱。一般都是单线程fork之后,才会开始多线程执行。
  • Go中多线程是runtime自行决定的,所以Go中没有提供单纯的fork,而是fork之后立即就exec执行新的二进制文件

为了实现上述需求,我们需要利用Go语言的一些特性进行模拟。

C语言的实现方式

在了解Go如何实现fork之前,先看一下C里的传统使用方式:

#include 
#include 
#include 
#include 

void child() {
    printf("child process\n");
}

int main() {
    printf("main process\n");
    pid_t pid = fork();
    int wstatus;

    if (pid == 0) {
        child();
    } else {
        printf("main exit\n");
        waitpid(pid, &wstatus, 0);
    }
}

运行一下:

$ gcc main.c && ./a.out 
main process
main exit
child process

Go语言的实现方案

见原文:https://jiajunhuang.com/articles/2018_03_08-golang_fork.md.html

你可能感兴趣的:(backend)