我如何分叉过程?

Sha*_*wat 11 fork exec go

我想分叉一个go进程并获取新进程的id,但我在库execos库中看到的只是启动一个新进程.

kos*_*tix 30

你应该syscall.ForkExec()syscall包中得到.

注意,这fork()是在没有使用任何线程的时候发明的,并且一个进程总是只有一个执行线程,因此分叉它是安全的.使用Go,情况完全不同,因为它大量使用操作系统级线程来支持其goroutine调度.

现在,fork(2)Linux上的unadorned 将使子进程只有单个线程 - fork(2)在父进程中调用的线程- 在所有活动的线程中,包括Go运行时使用的一些关键线程.基本上这意味着您根本无法期望子进程能够继续执行Go代码,并且您唯一可以明智地做的就是以某种方式立即执行exec(2).请注意,这syscall.ForkExec()就是所使用的内容.

现在进一步思考这个问题.我说现在直接调用的唯一fork(2)有用的是"尽力而为的异步进程状态快照" - 比如Redis使用的那种.这种技术依赖于子进程从其父进程继承所有内存数据页的事实,但操作系统使用写时复制技术并不真正复制所有数据,因此子进程可以坐在那里保存所有数据结构磁盘,而它的父进程在其自己的地址空间中修改它们.其他任何可以想象的用途fork()意味着立即exec(),这exec.Command()就是等等,为什么不使用呢?

  • "fork()的其他任何可能的用途都意味着立即执行exec(),这就是exec.Command()等所用的,为什么不使用呢?" 有setrlimit(),在移交控制之前设置SELinux,chroot(),关闭或设置FD - 那些需要在fork()和exec()之间发生,不是吗? (6认同)
  • @IvanVučica,Go在其`syscall.ForkExec()中直接支持这些东西:这个函数接受一个平台特性`syscall.ProcAttr`类型的实例,它可以访问各种各样的功能,包括继承FD,设置`cwd`,环境块,控制会话创建,chrooting,凭证,`clone(2)`标志等.我担心SELinux不受支持(AppArmor和朋友都不支持).有关详细信息,请参阅`go doc syscall.ProcAttr`和`go doc syscall.SysProcAttr`. (4认同)
  • @kostix:非常有用的见解和建议。回复:`fork()`:设想时,没有“在本地OS线程上具有某种抽象层的软件”,因为[UNIX直到近十年后才获得本地OS线程](http:// www.serpentine.com/blog/threads-faq/the-history-of-threads/)。:-) (2认同)