Go 中的 fork() 函数:为什么你应该使用 syscall.ForkExec()?
你可能需要使用 syscall 包中的 syscall.ForkExec()。
需要注意的是,fork() 是在没有使用线程的时代发明的,进程始终只有一个执行线程,因此 fork 它时是安全的。但是,在 Go 中,情况完全不同,因为它大量使用操作系统级别的线程来支持其 goroutine 调度。
现在,在 Linux 上使用未加修饰的 fork(2) 会使子进程只有一个线程——即在父进程中调用 fork(2) 的线程——在所有活动线程中,包括 Go 运行时使用的一些关键线程。基本上,这意味着你不能指望子进程能够继续执行 Go 代码,你唯一明智的做法就是立即执行 exec(2)。请注意,这就是 syscall.ForkExec() 的用途。
现在再进一步思考这个问题。我认为,现在直接调用 fork(2) 的唯一有用之处是 '尽力异步进程状态快照',例如 Redis 使用的那种技术。这种技术依赖于子进程继承其父进程的所有内存数据页面,但是操作系统使用写时复制技术,不会真正复制所有数据,因此子进程可以坐在那里将所有数据结构保存到磁盘上,而其父进程则在自己的地址空间中修改它们。除此之外,对于 fork() 的任何其他可想象的用途都意味着立即执行 exec(),而这就是 exec.Command() 等的用途,那为什么不直接使用它呢?
原文地址: https://www.cveoy.top/t/topic/kULo 著作权归作者所有。请勿转载和采集!