为什么在Windows上创build一个比Linux更昂贵的新进程?

我听说在Windows上创build一个新的进程比在Linux上花费更多。 这是真的? 有人可以解释为什么它更昂贵的技术原因,并提供背后的原因devise决定的历史原因?

mweerden:NT从一开始就是为多用户devise的,所以这不是一个真正的原因。 然而,对于这个过程来说,创build过程在NT上比在Unix上起着不重要的作用,与Unix相反,它支持多处理multithreading。

Rob,在使用COW的时候fork是比较便宜的,但事实上,fork之后大部分都是exec。 而且exec也必须加载所有图像。 因此,讨论fork的性能只是事实的一部分。

在讨论进程创build的速度时,区分NT和Windows / Win32可能是一个好主意。 就NT(即内核本身)而言,我不认为创build进程(NtCreateProcess)和线程创build(NtCreateThread)比平均Unix要慢得多。 可能会有一些更多的事情发生,但我不认为这里的性能差异的主要原因。

但是,如果你看看Win32,你会注意到它为进程创build增加了相当多的开销。 首先,它要求CSRSS通知有关LPC的stream程创build。 它至less需要加载kernel32,并且在进程被认为是一个完整的Win32进程之前,必须执行一些额外的簿记工作项目。 我们不要忘记parsing清单造成的所有额外开销,检查图像是否需要兼容性填充,检查软件限制策略是否适用,yada yada。

也就是说,除了创造一个过程,VA空间和最初的线索之外,我还看到所有必须做的小事情的总体放缓。 但正如一开始所说的 – 由于multithreading技术的优势在于多任务处理,唯一受这一额外开支严重影响的软件就是移植得不好的Unix软件。 尽pipe像Chrome和IE8这样的软件突然重新发现了多处理的好处,并开始经常启动和拆卸过程,

Unix有一个“fork”系统调用,它将当前进程“拆分”为两个进程,并为您提供与第一个进程相同的第二个进程(以fork调用的返回值为模)。 由于新进程的地址空间已经启动并且正在运行,所以这比在Windows中调用“CreateProcess”并使其加载exe映像,关联的dll等应该更便宜。

在fork情况下,操作系统可以为与这两个新进程相关联的内存页面使用“写入时复制”语义,以确保每个进程都获得自己随后修改的页面副本。

加上JP所说的:大部分开销属于Win32启动过程。

Windows NT内核实际上支持COW分支。 SFU (微软用于Windows的UNIX环境)使用它们。 但是,Win32不支持fork。 SFU进程不是Win32进程。 SFU与Win32正交:它们都是在同一个内核上构build的环境子系统。

除了对CSRSS的进程外LPC调用之外,在XP和更高版本中,还有一个对进程调用的应用程序兼容性引擎来查找应用程序兼容性数据库中的程序。 由于性能原因,此步骤会导致Microsoft提供了一个组策略选项的足够开销,以禁用WS2003上的兼容性引擎 。

Win32运行时库(kernel32.dll等)在启动时也会执行大量的registry读取和初始化操作,这些操作不适用于UNIX,SFU或本机进程。

本地进程(没有环境子系统)的创build速度非常快。 SFU的创build过程比Win32要less很多,所以它的创build过程也很快。

除了Rob Walker的答案:Nowadys你有像本地POSIX线程库的东西 – 如果你想。 但是很长一段时间,在unix世界中“委托”工作的唯一方法就是使用fork()(在很多情况下它仍然是首选)。 例如某种套接字服务器

  socket_accept()
叉子()
 (小孩)
    的handleRequest()
其他
     goOnBeingParent()

因此fork的实现必须很快,并且随着时间的推移已经实现了很多优化。 微软认可CreateThread甚至光纤,而不是创build新的进程和使用进程间通信。 我认为将CreateProcess与fork进行比较是不公平的,因为它们是不可互换的。 将fork / exec与CreateProcess进行比较可能更合适。

这个问题的关键是两个系统的历史用法,我想。 Windows(以及之前的DOS)最初是用于个人计算机的单用户系统。 因此,这些系统通常不必一直创build大量的stream程; (非常)简单地说,一个过程只在这个孤独的用户请求它时产生(我们人类相对来说操作起来不是很快)。

基于Unix的系统原来是多用户系统和服务器。 尤其对于后者来说,具有分离进程以处理特定作业(例如照顾一个传入连接)的进程(例如邮件或http守护进程)并不罕见。 这样做的一个重要因素是便宜的fork方法(Rob Walker( 47865 )提到,最初为新创build的进程使用相同的内存),这是非常有用的,因为新进程立即拥有所需的所有信息。

很显然,至less从历史上看,基于Unix的系统需要快速创buildstream程远远大于Windows系统。 我认为这仍然是这样的,因为基于Unix的系统仍然是非常面向stream程的,而Windows由于其历史的原因可能更多地是面向线程(线程对于做出响应式应用程序是有用的)。

免责声明:我绝不是这方面的专家,所以如果我错了,请原谅我。

简短的答案是“软件层和组件”。

Windows SW体系结构有一些额外的层和组件,它们在Unix上不存在,或者在Unix内核上进行简化和处理。

在Unix上,fork和exec是对内核的直接调用。

在Windows上,内核API不是直接使用,而是在其上面有win32和其他某些组件,因此进程创build必须经过额外的层,然后新进程必须启动或连接到这些层和组件。

相当长一段时间,研究人员和企业都试图以一种相似的方式分裂Unix,通常将他们的实验放在Mach内核上 ; 一个众所周知的例子是OS X. 但是,每次他们尝试的时候,都会变得非常缓慢,最终至less部分地将这些碎片永久性地合并到内核中,或者用于生产出货。

呃,似乎有很多“这样更好”的理由。

我认为人们可以通过阅读“Showstopper”获益。 关于Windows NT的发展的书。

在Windows NT上一个进程中运行DLL的全部原因是它们作为单独的进程太慢。

如果你沮丧,你会发现图书馆的加载策略是个问题。

在Unices上(一般情况下)共享库(DLL)的代码段实际上是共享的。

Windows NT加载每个进程的DLL副本,因为它加载后操纵库代码段(和可执行代码段)。 (告诉它你的数据在哪里?)

这会导致库中的代码段不可重用。

所以,NT进程创build实际上非常昂贵。 而在另一方面,它使DLL没有可观的节省内存,但是一个机会之间的应用程序依赖问题。

有时候,工程师会退后一步,说:“现在,如果我们要把这个devise成真的吸吮,它会是什么样子?”

我曾经使用过一种颇为气质的embedded式系统,有一天看着它,发现它是一个腔式磁控pipe,电子pipe在微波腔中。 之后,我们做得更加稳定(不像微波炉)。

所有这一切,再加上有一个事实,在赢机器上最有可能的一个杀毒软件将在CreateProcess期间踢…这通常是最大的放缓。

还值得注意的是,Windows中的安全模型比基于Unix的操作系统复杂得多,这在进程创build过程中增加了很多开销。 在Windows中multithreading优先于多处理的另一个原因。