`

[回溯本源] Unix Fork和Windows CreateProcess可以比较吗?

阅读更多
进程是现代操作系统的一个最基本的概念。书本上说:进程是一个具有独立功能的程序关于某个数据集合的一次运行活动。它可以申请和拥有系统资源,是一个动态的概念,是一个活动的实体。它不只是程序的代码,还包括当前的活动,通过程序计数器的值和处理寄存器的内容来表示。

详细点说:进程的概念主要有两点:

第一,进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。

第二,进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序生命时,它才能成为一个活动的实体,我们称其为进程。

在Unix系统中,我们通常用fork来创建一个进程,相应的,在Windows操作系统里,我们用的是CreateProcess,一些对两个平台不熟悉的程序员,常常误以为二者是等同的,并得出了诸如在Windows创建进程比在Unix慢许多等错误结论。

fork时发生了什么?
当fork()系统调用发生时,子进程会拷贝其父进程的所有页面,并将其加载入操作系统为它分配的一片独立内存中。这些拷贝的动作很消耗时间,而且在某些情况下并不需要这么做。如果子进程马上执行了"exec"系统调用(用来执行任何可执行文件)或者Fork()之后就退出进程,拷贝父进程的页面就很不划算,因为exec后包括代码段,数据段和堆栈等都已经被新的内容取代,只留下进程ID等一些表面上的信息仍保持原样,而如果fork完之后我们马上就调用exec,这些辛辛苦苦拷贝来的东西又会被立刻抹掉。

在这种情况下,一种叫copy-on-write (随拷随写)(COW)的技术被采用了,当fork发生时,父进程的页面并没有被拷贝到子进程中,相反,这些页面被父进程和子进程所共享。无论父子进程中谁要去修改页面,系统就为该进程拷贝一个独立的特定页面,然后再对其进行修改。该进程以后就只使用这个新拷贝的页面而不再是共享的那个,而别的进程则继续使用共享的页面。这项技术就叫随拷随写,因为当有进程要写页面的时候,就需要先拷贝页面。

采用了COW技术,Fork时,子进程只需要拷贝父进程的页面表就可以了。产生这种设计是因为有时兼容POSIX的操作系统在Fork之后,并不需要执行Exec,比如apache Web Server就因此而受益,这时候的fork让你想起点什么?恩,有点接近Windows的CreateThread。

socket_accept()
fork()
if (child)
    handleRequest()
else
    goOnBeeingParent()


COW技术使得创建子进程的代价小了许多,但是现实情况下,很多时候Fork会紧跟着一个EXEC,因为Exec必须装载所有的映像,unix还是得花很大的代价来创建一个进程。

阐述到这里,比较公平的比较是 Fork近似于NtCreateThread 而CreateProcess 近似于 fork + execve.

这里为什么说比较公平而已,因为还有别的因素我们还未涉及。

相对于Unix,Windows的设计更有弹性,它是一个多层次的而且更加组件化的操作系统,Windows拥有许多子系统,我们通常说的Windows,只是它的子系统之一,称为WoW(Windows On Windows),其他子系统还包括Wow64,Posix和OS2。 Windows NT内核也支持COW fork,但是只为SFU(Microsoft's UNIX environment for Windows)所使用,SFU进程和Win32进程是不同的东西。

回到Win32的进程创建上来,你会发现Windows为Win32进程创建的过程添加了许多枝节。首先,它需要通知CSRSS进程被创建,CSRSS又调用了LPC,而它要求至少kernel32(NTDll.dll)等动态库要被加载,然后它又要处理许多预保留的工作项目,之后该进程才能被认为是一个Win32进程,之后还有许多枝节要去处理比如解析manifests,程序兼容性检查,程序的限制策略等等等等,这些附加在原始进程创建过程之后枝节,无疑拖累了进程创建速度。

这些巴拉巴拉的事情,让我想起了struts,一个又一个filter被插入一次http request之后。

MS提供了一个组策略可以禁用兼容性检查,这样可以大大提高进程的创建速度。此外Win32的运行库(kernel32.dll等等)还带来了大量注册表读操作和初始化。这些东西对 UNIX, SFU或者原生进程都是不存在的。

不带任何子系统的原生进程的创建速度是很快的,而创建SFU进程要比Win32进程简单得多,也快得多,尽管Win32花了许多力气在加载这些枝节之上,但是一方面,它提高了对客户的友好,另一方面,运行库的预加载使得图形界面的处理速度更快,或者Win32进程天生就是为图形处理做准备的。

运行在Windows里Unix Subsystem之上的XClock.



SFU不是unix仿真系统:


  • 大小: 61.7 KB
  • 大小: 21.8 KB
分享到:
评论
2 楼 mallon 2010-06-18  
1、WOW提供的是16位Windows的兼容层,可以把它看成是一个16位的模拟器,类似于NTVDM模拟16位DOS一样

2、很多所谓的“子系统”,例如Posix,其实只是一个或几个DLL,按照Posix的标准把底层的API包装了一下而已,甚至大名鼎鼎的OpenGL也是对DirectX的简单包装

3、Windows的设计其实是很拙劣的,文中最后所讲的“Windows的设计更有弹性,它是一个多层次的而且更加组件化的操作系统”等等其实正是Windows的缺点,没办法,商业化带来的后果就是设计思想的匮乏和越积越多的历史包袱
1 楼 mathgl 2010-05-12  
现在我就算在win32下作server的开发,也是优先考虑使用 multi-process。提高健壮性和负载能力。

相关推荐

    创建新进程:fork函数:fork函数干什么? fork函数与vfork函数的区别在哪里?为何在一个fork的子进程分支中使用_exit函数而不使用exit函数?

    fork 函数是 UNIX 统操作系统中用于创建新进程的系统调用。它创建了一个完全相同的子进程副本,并返回一个进程标识符(PID)。fork 函数的返回值在父进程和子进程中不同:在父进程中,返回子进程的 PID;在子进程中...

    Git-Fork for Windows

    https://git-fork.com/update/win/ForkInstaller.exe windows桌面版的图形化Git管理工具

    linux下socket和fork结合使用的例子

    `socket`用于创建通信端点,允许不同进程间进行数据交换,`fork`则是Unix/Linux系统中用于创建新进程的关键系统调用。本示例中,我们将深入探讨如何将它们结合使用,以实现一个简单的服务器程序,该程序可以接收...

    VC编程-UNIX与Windows移植.doc

    例如,UNIX中的fork()函数在Windows中没有直接等价物,需要使用CreateProcess()或Spawn*()函数来创建新进程。同时,进程间通信在两个系统中也有所不同,UNIX使用管道、消息队列和共享内存,而Windows则有自己的一套...

    Fork目前发现最好用的git-ui免费客户端(mac + Window版本)备忘

    在众多的Git UI客户端中,Fork被誉为macOS和Windows平台上的优秀选择。本文将详细探讨Fork作为Git UI客户端的优势及其核心特性。 标题中的"Fork目前发现最好用的git-ui免费客户端"表明,Fork在用户界面设计、功能集...

    git客户端fork安装包

    8. **Stash和Unstaged Changes**:Fork支持暂存区和未暂存区的操作,用户可以轻松地将更改暂时保存,以便稍后再进行提交。 9. **SSH密钥管理**:Fork可以方便地配置和管理SSH密钥,确保安全地连接到远程Git仓库。 ...

    带注释的fork文件.rtf

    * linux/kernel/fork.c * * (C) 1991 Linus Torvalds */ /* * 'fork.c' contains the help-routines for the 'fork' system call * (see also system_call.s), and some misc functions ('verify_area'). *...

    fork(Mac & Windows).zip

    高颜值的git客户端——fork,高度集成git操作,方便好用,add、commit、solve conflict 变得形象而简单。可以免费使用,偶尔会提醒购买软件,点击忽略即可。包含 Mac 和 Windows 安装包。

    Fork-1.0.91.1.dmg

    适用于Mac和Windows的快速友好的git客户端 Fork日新月异,我们很高兴与您分享我们的成果。 Fork会轻松地向您通知有关GitHub通知的信息,而不会令人烦恼。 使用合并冲突帮助程序和内置的合并冲突解决程序可以轻松...

    fork()编程fork()编程fork()编程

    在Linux和Unix操作系统中,`fork()`函数是创建新进程的核心机制。`fork()`编程是系统调用的一个重要部分,它允许一个正在运行的进程(父进程)创建一个与自身几乎完全相同的副本(子进程)。这个特性使得多进程编程...

    nohup、&、setsid、fork和fg、bg究竟有啥区别?

    子进程从父进程继承了:SessionID、进程组ID和打开的终端。子进程如果要脱离这些,代码中可通过调用setsid来实现。,而命令行或脚本中可以通过使用命令setsid来运行程序实现。setsid帮助一个进程脱离从父进程继承而...

    unix程序员手册.zip_UNIX_unix程序员手册

    通过《UNIX程序员手册》,新手不仅可以学习到UNIX系统的基础知识,还能深入理解其设计哲学和工作原理,为后续的系统级编程和高级应用开发打下坚实基础。这本书不仅是入门工具,更是长期参考资料,值得反复研读和实践...

    Fork 解读

    1.1 定义:Fork是Unix/Linux操作系统提供的一种系统调用,通过这个调用,一个正在运行的进程(父进程)可以创建出一个与其完全一样的新进程(子进程)。两个进程拥有相同的内存空间布局,包括代码、数据和堆栈,但...

    tar for windows windows运行tar打包工具

    在Windows操作系统中,通常我们使用的是与Unix/Linux系统不同的文件管理和打包工具,如7-Zip或WinRAR。然而,对于习惯于Unix/Linux环境的开发者和系统管理员,`tar`命令是一个不可或缺的工具,它能方便地进行文件...

    fork3()编程fork3()编程fork3()编程fork3()编程fork3()编程

    在Linux和Unix操作系统中,`fork3()`是一个不常见的术语,通常我们使用的进程创建函数是`fork()`. 可能这里的`fork3()`是某种特定情境下的命名或者误解,但在此我们将基于标准的`fork()`函数来讨论进程创建的相关...

    在win系统下模拟linux中的fork()函数执行过程与基础通信过程

    在win系统下模拟linux中的fork()函数执行过程与基础通信过程 备注清晰。

    Fork安装包,Git可视化操作工具

    在 Fork 的主界面上,你可以看到仓库的提交历史,分支列表以及其他信息。 创建分支: 在 Fork 中,你可以点击 "Branches"(分支)按钮来查看分支列表。 点击 "New Branch"(新建分支)按钮来创建一个新的分支,然后...

    FORK工具git管理工具

    2. **智能提示与预览**: 在提交前,FORK可以自动检测和提示未添加到暂存区的文件,同时支持对即将提交的更改进行预览,确保提交的内容符合预期。 3. **分支管理**: FORK支持一键创建、合并分支,以及通过可视化图表...

    unix系统编程源代码

    本源代码分析着重于理解和解析这些底层机制。 一、进程与线程管理 Unix系统中的进程是程序执行的实例,每个进程都有独立的内存空间。通过`fork()`函数可以创建新进程,`exec()`系列函数用于加载新的程序到已创建的...

    fork1() 编程fork1() 编程fork1() 编程fork1() 编程

    它通常用于表示一个进程创建新进程的过程,这是Unix和类Unix系统(如Linux)中的一个核心功能。`fork1()` 可能是`fork()` 函数的一个特例或变体,但在标准的POSIX系统调用中,并没有`fork1()` 这个单独的函数,通常...

Global site tag (gtag.js) - Google Analytics