Windows 最接近 fork() 的是什么?

2021-12-02 00:00:00 windows c fork c++

我想这个问题说明了一切.

I guess the question says it all.

我想在 Windows 上分叉.最相似的操作是什么,如何使用.

I want to fork on Windows. What is the most similar operation and how do I use it.

推荐答案

Cygwin 有全功能的 fork()在 Windows 上.因此,如果您可以接受使用 Cygwin,那么在性能不成问题的情况下,问题就解决了.

Cygwin has fully featured fork() on Windows. Thus if using Cygwin is acceptable for you, then the problem is solved in the case performance is not an issue.

否则你可以看看Cygwin是如何实现fork()的.来自相当古老的 Cygwin 架构 doc:

Otherwise you can take a look at how Cygwin implements fork(). From a quite old Cygwin's architecture doc:

5.6.流程创建Cygwin 中的 fork 调用特别有趣因为它不能很好地映射在Win32 API.这使它很难以正确实施.目前,Cygwin fork 是一个非写时复制实现类似于早期出现的UNIX 的风格.

5.6. Process Creation The fork call in Cygwin is particularly interesting because it does not map well on top of the Win32 API. This makes it very difficult to implement correctly. Currently, the Cygwin fork is a non-copy-on-write implementation similar to what was present in early flavors of UNIX.

发生的第一件事父进程派生一个子进程是父初始化一个空间在 Cygwin 进程表中孩子.然后它创建一个暂停使用 Win32 的子进程CreateProcess 调用.接下来,家长进程调用 setjmp 来保存自己的上下文并设置一个指向 this 的指针Cygwin 共享内存区域(共享在所有 Cygwin 任务中).然后填满在孩子的 .data 和 .bss 部分通过从它自己的地址空间复制进入暂停儿童的地址空间.在孩子的地址空间之后被初始化,子进程同时运行父级等待互斥锁.孩子发现它已经分叉并且longjumps 使用保存的跳转缓冲区.然后孩子将互斥锁设置为父母正在等待并阻止另一个互斥锁.这是信号复制其堆栈和堆的父级进入孩子,然后它释放孩子所在的互斥锁等待并从叉子返回称呼.最后,孩子从在最后一个互斥锁上阻塞,重新创建任何传递给它的内存映射区域通过共享区域,并从分叉本身.

The first thing that happens when a parent process forks a child process is that the parent initializes a space in the Cygwin process table for the child. It then creates a suspended child process using the Win32 CreateProcess call. Next, the parent process calls setjmp to save its own context and sets a pointer to this in a Cygwin shared memory area (shared among all Cygwin tasks). It then fills in the child's .data and .bss sections by copying from its own address space into the suspended child's address space. After the child's address space is initialized, the child is run while the parent waits on a mutex. The child discovers it has been forked and longjumps using the saved jump buffer. The child then sets the mutex the parent is waiting on and blocks on another mutex. This is the signal for the parent to copy its stack and heap into the child, after which it releases the mutex the child is waiting on and returns from the fork call. Finally, the child wakes from blocking on the last mutex, recreates any memory-mapped areas passed to it via the shared area, and returns from fork itself.

虽然我们有一些关于如何通过以下方式加快我们的分叉实施减少上下文的数量在父子之间切换进程,fork 几乎肯定会在 Win32 下总是效率低下.幸运的是,在大多数情况下spawn 提供的调用系列Cygwin 可以代替fork/exec 对只有一点点努力.这些调用清晰地映射在顶部Win32 API.结果,他们效率更高.改变编译器的驱动程序调用spawn 而不是 fork 是微不足道的改变和增加编译速度提高百分之二十到三十我们的测试.

While we have some ideas as to how to speed up our fork implementation by reducing the number of context switches between the parent and child process, fork will almost certainly always be inefficient under Win32. Fortunately, in most circumstances the spawn family of calls provided by Cygwin can be substituted for a fork/exec pair with only a little effort. These calls map cleanly on top of the Win32 API. As a result, they are much more efficient. Changing the compiler's driver program to call spawn instead of fork was a trivial change and increased compilation speeds by twenty to thirty percent in our tests.

然而,spawn 和 exec 展示了他们的自己的一系列困难.因为那里没有办法在下面做一个实际的 execWin32,Cygwin 得自己发明进程 ID (PID).结果,当一个进程执行多个exec调用,会有多个Windows与单个 Cygwin 关联的 PIDPID.在某些情况下,每个的存根这些 Win32 进程可能会逗留,等待他们执行的 Cygwin进程退出.

However, spawn and exec present their own set of difficulties. Because there is no way to do an actual exec under Win32, Cygwin has to invent its own Process IDs (PIDs). As a result, when a process performs multiple exec calls, there will be multiple Windows PIDs associated with a single Cygwin PID. In some cases, stubs of each of these Win32 processes may linger, waiting for their exec'd Cygwin process to exit.

听起来工作量很大,不是吗?是的,它太慢了.

Sounds like a lot of work, doesn't it? And yes, it is slooooow.

文档已过时,请参阅此优秀回答 更新

the doc is outdated, please see this excellent answer for an update

相关文章