Answers:
mweerden:NT从一开始就为多用户设计的,因此这并不是真正的原因。但是,您对的是,进程创建在NT上的作用不如在Unix上重要,因为与Unix相比,NT与Unix相比,主张多线程而不是多处理。
Rob,确实,使用COW时fork相对便宜,但是事实上,fork后面紧跟着一个执行程序。执行人员也必须加载所有图像。因此,讨论前叉的性能只是事实的一部分。
在讨论进程创建的速度时,最好区分NT和Windows / Win32。就NT(即内核本身)而言,我认为进程创建(NtCreateProcess)和线程创建(NtCreateThread)不会比一般Unix显着慢。可能还有更多事情要做,但是我看不出性能差异的主要原因。
但是,如果您查看Win32,您会注意到它会增加很多创建过程的开销。首先,它要求CSRSS通知有关过程创建的过程,这涉及LPC。它至少需要另外加载kernel32,并且必须执行许多其他的簿记工作项目,然后才能将该进程视为完整的Win32进程。而且,我们不要忘记解析清单所带来的所有额外开销,检查映像是否需要兼容性填充程序,检查软件限制策略是否适用(yada yada)。
就是说,除了进程的原始创建,VA空间和初始线程之外,我还看到所有必须做的小事情的总和总体下降。但是正如一开始所说的那样-由于多线程比多任务更受青睐,因此唯一受到此额外费用严重影响的软件就是移植性差的Unix软件。尽管当Chrome和IE8之类的软件突然重新发现多处理的优势并开始频繁启动和拆卸过程时,这种情况发生了变化。
Unix有一个“ fork”系统调用,该系统调用将当前进程“拆分”为两个,并为您提供与第一个进程相同的第二个进程(对fork调用的返回进行模运算)。由于新进程的地址空间已经启动并正在运行,因此它比在Windows中调用'CreateProcess'并加载exe映像,关联的dll等便宜。
在分叉的情况下,OS可以对与这两个新进程相关联的内存页面使用“写时复制”语义,以确保每个人都获得他们自己随后修改的页面的副本。
JP补充说:该过程的大部分开销属于Win32启动。
Windows NT内核实际上确实支持COW fork。SFU(用于Windows的Microsoft UNIX环境)使用它们。但是,Win32不支持fork。SFU进程不是Win32进程。SFU与Win32正交:它们都是基于同一内核构建的环境子系统。
在CSRSS
XP和更高版本中,除了对LPC 的进程外调用之外,还存在对应用程序兼容性引擎的进程外调用,以在应用程序兼容性数据库中查找程序。此步骤导致足够的开销,Microsoft 出于性能原因提供了一个组策略选项来禁用WS2003上的兼容性引擎。
Win32运行时库(kernel32.dll等)在启动时还会执行很多注册表读取和初始化操作,这些操作不适用于UNIX,SFU或本机进程。
本机进程(没有环境子系统)创建起来非常快。SFU在创建过程方面比Win32少得多,因此它的过程创建起来也很快。
2019年更新:添加LXSS:Linux的Windows子系统
LXSS环境子系统是替换Windows 10的SFU。它是100%内核模式,不需要Win32继续拥有的任何IPC。这些进程的系统调用直接定向到lxss.sys / lxcore.sys,因此fork()或其他创建调用的进程对于创建者仅花费1个系统调用,总计。[称为实例的数据区域]跟踪所有LX进程,线程和运行时状态。
LXSS进程基于本机进程,而不是Win32进程。完全没有使用诸如兼容性引擎之类的所有Win32特定功能。
除了Rob Walker的答案:如今,如果需要,您还可以使用Native POSIX Thread Library之类的东西。但是很长一段时间以来,在unix世界中“委托”工作的唯一方法是使用fork()(在许多情况下,它仍然是首选)。例如某种套接字服务器
socket_accept() 叉子() 如果(孩子) handleRequest() 其他 goOnBeingParent()因此,fork的实现必须快速,并且随着时间的推移已经实现了很多优化。Microsoft认可了CreateThread甚至光纤,而不是创建新进程和使用进程间通信。我认为将CreateProcess与fork进行比较是不公平的,因为它们不可互换。将fork / exec与CreateProcess进行比较可能更合适。
我认为,这件事的关键是两个系统的历史用法。Windows(以前是DOS)最初是个人计算机的单用户系统。因此,这些系统通常不必始终创建很多进程;(非常)简单地说,只有在这个孤独的用户请求时才会创建一个流程(相对而言,我们人类的运行速度并不快)。
基于Unix的系统最初是多用户系统和服务器。特别是对于后者,让进程(例如邮件或http守护程序)分离出来以处理特定作业(例如照顾一个传入连接)的情况并不少见。这样做的一个重要因素是便宜的fork
方法(如Rob Walker(47865)所述,最初为新创建的进程使用相同的内存),这非常有用,因为新进程会立即获得所需的所有信息。
显然,至少从历史上看,基于Unix的系统具有快速的进程创建的需求远远大于Windows系统。我认为情况仍然如此,因为基于Unix的系统仍然非常面向过程,而Windows由于其历史悠久,可能更多地面向线程(线程对于响应式应用程序很有用)。
免责声明:我绝不是这个问题的专家,如果我理解错了,请原谅我。
嗯,似乎有很多“这样更好”的理由。
我认为人们可以从阅读“ Showstopper”中受益。关于Windows NT开发的书。
在Windows NT上,服务在一个进程中以DLL的形式运行的全部原因是,它们作为单独的进程太慢了。
如果您摔倒了,就会发现库加载策略是问题所在。
实际上,在Unices上,共享库(DLL)的代码段实际上是共享的。
Windows NT会为每个进程加载DLL的副本,因为它会在加载后操纵库代码段(和可执行代码段)。(告诉您您的数据在哪里?)
这导致库中的代码段不可重用。
因此,NT进程创建实际上非常昂贵。不利的一面是,它使DLL没有明显的内存节省,但有可能导致应用间依赖问题。
有时候回头说“现在,如果我们要设计出真正吸引人的东西,那会是什么样子呢?”
我曾经使用过一种非常有气质的嵌入式系统,有一天看着它,发现它是一个空腔磁控管,而电子器件位于微波空腔中。在那之后,我们使它变得更加稳定(而不像微波炉)。
Windows SW体系结构具有Unix上不存在或在Unix上的内核内部进行简化和处理的几个附加层和组件。
在Unix上,fork和exec是对内核的直接调用。
在Windows上,不直接使用内核API,它上面没有win32和某些其他组件,因此进程创建必须经过额外的层,然后新进程必须启动或连接到这些层和组件。
一段时间以来,研究人员和公司一直试图以一种模糊的相似方式来破坏Unix,通常将他们的实验基于Mach内核。一个著名的例子是OSX。但是,每次尝试时,它都变得如此缓慢,最终最终导致它们至少部分地永久性地或为了生产目的而部分地合并回内核。
似乎在某些答案中有一些MS-Windows的理由,例如
数据汇总自http://www.bitsnbites.eu/benchmarking-os-primitives/。
由于偏差是不可避免的,因此在总结时,我在大多数i7 8核心3.2GHz测试中都偏爱MS-Windows
硬件。除了运行Gnu / Linux的Raspberry-Pi
注意:在linux上,fork
它比MS-Window的首选方法更快CreateThread
。
按照速度的顺序,从最快到最慢(数字是时间,小的代表更好)。
还值得注意的是,Windows中的安全模型比基于UNIX的OS复杂得多,这在创建过程中增加了很多开销。在Windows中,多线程优先于多处理的另一个原因。
fork()