Windows 与 fork() 最接近的东西是什么?
我想在 Windows 上 fork。 最相似的操作是什么?如何使用它?
I want to fork on Windows. What is the most similar operation, and how do I use it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(15)
如果您只关心创建子进程并等待它,也许 process.h 中的 _spawn* API 就足够了。 以下是有关此内容的更多信息:
https: //learn.microsoft.com/en-us/cpp/c-runtime-library/process-and-environment-control
https://en.wikipedia.org/wiki/Process.h
If you only care about creating a subprocess and waiting for it, perhaps _spawn* API's in process.h are sufficient. Here's more information about that:
https://learn.microsoft.com/en-us/cpp/c-runtime-library/process-and-environment-control
https://en.wikipedia.org/wiki/Process.h
与“Eric de Courtis”相关的最新链接
回答了此处:
forkWindows.h
>forkWindows.c(已删除)
。 .. 问候 !
Up-To-Date link(s), relating to what "Eric de Courtis"
answered HERE:
forkWindows.h
forkWindows.c (stripped)
... regards !
Cygwin 在 Windows 上具有功能齐全的 fork()。 因此,如果您可以接受使用 Cygwin,那么在性能不是问题的情况下问题就解决了。
否则你可以看看Cygwin是如何实现fork()的。 来自相当古老的 Cygwin 架构 doc:
听起来工作量很大,不是吗? 是的,它很慢。
编辑:该文档已过时,请参阅这个优秀的 回答更新
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:
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
我当然不知道这方面的细节,因为我从来没有这样做过,但是本机 NT API 具有分叉进程的功能(Windows 上的 POSIX 子系统需要此功能 - 我不确定 POSIX 子系统是否甚至不再支持)。
搜索 ZwCreateProcess() 应该会为您提供更多详细信息 - 例如 来自 Maxim Shatskih 的信息:
但请注意 Corinna Vinschen 表示 Cygwin 使用 ZwCreateProcess 发现() 仍然不可靠:
I certainly don't know the details on this because I've never done it it, but the native NT API has a capability to fork a process (the POSIX subsystem on Windows needs this capability - I'm not sure if the POSIX subsystem is even supported anymore).
A search for ZwCreateProcess() should get you some more details - for example this bit of information from Maxim Shatskih:
Though note that Corinna Vinschen indicates that Cygwin found using ZwCreateProcess() still unreliable:
嗯,Windows 确实没有类似的东西。 特别是因为 fork 可以在概念上用于在 *nix 中创建线程或进程。
所以,我不得不说:
CreateProcess()
/CreateProcessEx()
和
CreateThread()
(我听说对于 C 应用程序,_beginthreadex()
更好)。Well, windows doesn't really have anything quite like it. Especially since fork can be used to conceptually create a thread or a process in *nix.
So, I'd have to say:
CreateProcess()
/CreateProcessEx()
and
CreateThread()
(I've heard that for C applications,_beginthreadex()
is better).人们尝试在 Windows 上实现 fork。 这是我能找到的最接近的东西:
取自:http://doxygen.scilab。 org/5.3/d0/d8f/forkWindows_8c_source.html#l00216
People have tried to implement fork on Windows. This is the closest thing to it I can find:
Taken from: http://doxygen.scilab.org/5.3/d0/d8f/forkWindows_8c_source.html#l00216
正如其他答案所提到的,NT(现代 Windows 版本的底层内核)具有相当于 Unix fork() 的功能。 那不是问题。
问题在于,克隆进程的整个状态通常不是一件明智的事情。 这在 Unix 世界和 Windows 中都是如此,但在 Unix 世界中,一直使用 fork(),并且库被设计来处理它。 Windows 库则不然。
例如,系统 DLL kernel32.dll 和 user32.dll 维护与 Win32 服务器进程 csrss.exe 的专用连接。 分叉后,该连接的客户端有两个进程,这会导致问题。 子进程应该通知 csrss.exe 它的存在并建立一个新的连接 - 但没有接口可以做到这一点,因为这些库在设计时没有考虑到 fork()。
所以你有两个选择。 一是禁止使用 kernel32 和 user32 以及其他并非旨在分叉的库 - 包括任何直接或间接链接到 kernel32 或 user32 的库,这实际上是所有库。 这意味着您根本无法与 Windows 桌面交互,并且被困在您自己独立的 Unixy 世界中。 这是 NT 的各种 Unix 子系统所采用的方法。
另一种选择是采用某种可怕的黑客手段来尝试让不知情的库使用 fork()。 这就是 Cygwin 所做的。 它创建一个新进程,让它初始化(包括向 csrss.exe 注册自身),然后从旧进程复制大部分动态状态,并希望得到最好的结果。 令我惊讶的是,这曾经有效。 它当然不能可靠地工作——即使它不会由于地址空间冲突而随机失败,您正在使用的任何库都可能会默默地处于损坏状态。 当前接受的答案声称 Cygwin 具有“功能齐全的 fork()”,这是......可疑的。
简介: 在类似Interix 的环境中,您可以通过调用fork() 来进行分叉。 否则,请尝试戒掉这样做的欲望。 即使您的目标是 Cygwin,也不要使用 fork(),除非绝对必要。
As other answers have mentioned, NT (the kernel underlying modern versions of Windows) has an equivalent of Unix fork(). That's not the problem.
The problem is that cloning a process's entire state is not generally a sane thing to do. This is as true in the Unix world as it is in Windows, but in the Unix world, fork() is used all the time, and libraries are designed to deal with it. Windows libraries aren't.
For example, the system DLLs kernel32.dll and user32.dll maintain a private connection to the Win32 server process csrss.exe. After a fork, there are two processes on the client end of that connection, which is going to cause problems. The child process should inform csrss.exe of its existence and make a new connection – but there's no interface to do that, because these libraries weren't designed with fork() in mind.
So you have two choices. One is to forbid the use of kernel32 and user32 and other libraries that aren't designed to be forked – including any libraries that link directly or indirectly to kernel32 or user32, which is virtually all of them. This means that you can't interact with the Windows desktop at all, and are stuck in your own separate Unixy world. This is the approach taken by the various Unix subsystems for NT.
The other option is to resort to some sort of horrible hack to try to get unaware libraries to work with fork(). That's what Cygwin does. It creates a new process, lets it initialize (including registering itself with csrss.exe), then copies most of the dynamic state over from the old process and hopes for the best. It amazes me that this ever works. It certainly doesn't work reliably – even if it doesn't randomly fail due to an address space conflict, any library you're using may be silently left in a broken state. The claim of the current accepted answer that Cygwin has a "fully-featured fork()" is... dubious.
Summary: In an Interix-like environment, you can fork by calling fork(). Otherwise, please try to wean yourself from the desire to do it. Even if you're targeting Cygwin, don't use fork() unless you absolutely have to.
在 Microsoft 推出新的“Windows Linux 子系统”选项之前,
CreateProcess()
是 Windows 与fork()
最接近的东西,但 Windows 要求您指定一个可执行文件在该过程中运行。UNIX 进程的创建与Windows 有很大不同。 它的 fork() 调用基本上几乎完全复制了当前进程,每个进程都在自己的地址空间中,并继续单独运行它们。 虽然进程本身不同,但它们仍然运行相同的程序。请参阅这里可以很好地概述
fork/exec
模型。反过来说,Windows
CreateProcess()
的等价物是 UNIX 中的fork()/exec()
对函数。如果您将软件移植到 Windows 并且不介意翻译层,Cygwin 提供了您想要的功能,但它相当混乱。
当然,新的 Linux 子系统 ,Windows 与
fork()
最接近的东西是实际上fork()
:-)Prior to Microsoft introducing their new "Linux subsystem for Windows" option,
CreateProcess()
was the closest thing Windows has tofork()
, but Windows requires you to specify an executable to run in that process.The UNIX process creation is quite different to Windows. Its
fork()
call basically duplicates the current process almost in total, each in their own address space, and continues running them separately. While the processes themselves are different, they are still running the same program. See here for a good overview of thefork/exec
model.Going back the other way, the equivalent of the Windows
CreateProcess()
is thefork()/exec()
pair of functions in UNIX.If you were porting software to Windows and you don't mind a translation layer, Cygwin provided the capability that you want but it was rather kludgey.
Of course, with the new Linux subsystem, the closest thing Windows has to
fork()
is actuallyfork()
:-)以下文档提供了有关将代码从 UNIX 移植到 Win32 的一些信息:
https://msdn.microsoft.com/en-us/library/y23kc048。除此之外
,它表明两个系统之间的进程模型有很大不同,并且建议在需要类似 fork() 的行为时考虑 CreateProcess 和 CreateThread。
The following document provides some information on porting code from UNIX to Win32:
https://msdn.microsoft.com/en-us/library/y23kc048.aspx
Among other things, it indicates that the process model is quite different between the two systems and recommends consideration of CreateProcess and CreateThread where fork()-like behavior is required.
“一旦你想要进行文件访问或 printf,那么 io 就会被拒绝”
鱼和熊掌不可兼得……在 msvcrt.dll 中,printf() 基于 Console API,它本身使用 lpc 与控制台子系统 (csrss.exe) 进行通信。 与 csrss 的连接是在进程启动时启动的,这意味着任何“在中间”开始执行的进程都将跳过该步骤。 除非您有权访问操作系统的源代码,否则尝试手动连接 csrss 是没有意义的。 相反,您应该创建自己的子系统,并相应地避免使用 fork() 的应用程序中的控制台函数。
一旦您实现了自己的子系统,请不要忘记为子进程复制所有父进程的句柄;-)
“此外,除非处于内核模式,否则您可能不应该使用 Zw* 函数,您可能应该使用 Nt* 函数。”
ZwGetContextThread(NtCurrentThread(), &context);
"as soon as you want to do file access or printf then io are refused"
You cannot have your cake and eat it too... in msvcrt.dll, printf() is based on the Console API, which in itself uses lpc to communicate with the console subsystem (csrss.exe). Connection with csrss is initiated at process start-up, which means that any process that begins its execution "in the middle" will have that step skipped. Unless you have access to the source code of the operating system, then there is no point in trying to connect to csrss manually. Instead, you should create your own subsystem, and accordingly avoid the console functions in applications that use fork().
once you have implemented your own subsystem, don't forget to also duplicate all of the parent's handles for the child process;-)
"Also, you probably shouldn't use the Zw* functions unless you're in kernel mode, you should probably use the Nt* functions instead."
ZwGetContextThread(NtCurrentThread(), &context);
您最好的选择是 CreateProcess() 或 CreateThread()。 此处提供了有关移植的更多信息。
Your best options are CreateProcess() or CreateThread(). There is more information on porting here.
没有简单的方法可以在 Windows 上模拟 fork()。
我建议您改用线程。
There is no easy way to emulate fork() on Windows.
I suggest you to use threads instead.
你说的最接近...让我想想...我想这一定是 fork() :)
有关详细信息,请参阅 Interix 是否实现 fork( )?
The closest you say... Let me think... This must be fork() I guess :)
For details see Does Interix implement fork()?
当子进程需要访问父进程在调用 fork() 时的实际内存状态时,fork() 语义是必要的。 我有一个软件,它依赖于调用即时 fork() 时内存复制的隐式互斥体,这使得线程无法使用。 (这是通过写时复制/更新内存表语义在现代 *nix 平台上模拟的。)
Windows 上最接近的系统调用是 CreateProcess。 最好的办法是父进程在将内存复制到新进程的内存空间期间冻结所有其他线程,然后解冻它们。 我可以看到,Cygwin frok [原文如此] 类和 Eric des Courtis 发布的 Scilab 代码都没有执行线程冻结。
另外,除非处于内核模式,否则您可能不应该使用 Zw* 函数,而应该使用 Nt* 函数。 有一个额外的分支检查您是否处于内核模式,如果不是,则执行 Nt* 始终执行的所有边界检查和参数验证。 因此,从用户模式调用它们的效率稍低。
fork() semantics are necessary where the child needs access to the actual memory state of the parent as of the instant fork() is called. I have a piece of software which relies on the implicit mutex of memory copying as of the instant fork() is called, which makes threads impossible to use. (This is emulated on modern *nix platforms via copy-on-write/update-memory-table semantics.)
The closest that exists on Windows as a syscall is CreateProcess. The best that can be done is for the parent to freeze all other threads during the time that it is copying memory over to the new process's memory space, then thaw them. Neither the Cygwin frok [sic] class nor the Scilab code that Eric des Courtis posted does the thread-freezing, that I can see.
Also, you probably shouldn't use the Zw* functions unless you're in kernel mode, you should probably use the Nt* functions instead. There's an extra branch that checks whether you're in kernel mode and, if not, performs all of the bounds checking and parameter verification that Nt* always do. Thus, it's very slightly less efficient to call them from user mode.
大多数黑客解决方案都已经过时了。 Winnie the fuzzer 有一个适用于当前版本的 Windows 10 的 fork 版本(尽管这需要系统特定的偏移量,并且也很容易崩溃)。
https://github.com/sslab-gatech/winnie/tree/master/叉库
Most of the hacky solutions are outdated. Winnie the fuzzer has a version of fork that works on current versions of Windows 10 (tho this requires system specific offsets and can break easily too).
https://github.com/sslab-gatech/winnie/tree/master/forklib