What's the Best Way to Duplicate Fork() in Windows

What is the closest thing Windows has to fork()?

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.

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

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.

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.

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.

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.

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

Substitute for forking in windows

fork() obviously doesn't exist on Windows. Instead you'll need to create a new thread, or a whole new process.

What's the equivalence of os.fork() on Windows with Python?

Depending on your use case and whether you can use python 2.6 or not, you might be able to use the multiprocessing module.

How can I start a sub-process in Windows?

There is no direct equivalent of fork() on Windows.

CreateProcess() is the native function that can be used to create a new process (but, again, the semantics are rather different to fork()'s).

To put this another way, on Unix it is possible for a process to cheaply create a clone of itself. There is no inexpensive way to do this on Windows.

If you don't care about the cloning aspect of fork(), then CreateProcess() should do just fine.

How to duplicate current process?

As @DavidHeffernan commented:

STARTUPINFO si;
::memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
PROCESS_INFORMATION pi;
::CreateProcess(NULL, ::GetCommandLine(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);

Linux fork function compared to Windows' CreateProcess - what gets copied?

When you call fork() then initially only your VM is copied and all pages are marked copy-on write. Your new child process will have a logical copy of your parent processes VM, but it will not consume any additional RAM until you actually start writing to it.

As for threads, fork creates only one new thread in the child process that resembles a copy of the calling thread.

Also as soon as you call any of the exec family of calls (which I assume you want to) then your entire process image is replaced with a new one and only file descriptors are kept.

If your parent process has a lot of open file descriptors then I suggest you go through /proc/self/fd and close all file descriptors in the child that you don't need.



Related Topics



Leave a reply



Submit