exec的不同实现--鸠占鹊巢还是功成身退

exec函数可以执行一个进程,是Run-Time Library里面的特性,标准上并没有给出什么硬性规定,因此各个操作系统平台上就可以有五花八门的实现了,本文介绍linux上的实现鸠占鹊巢和windows下的实现功成身退。
在linux上,著名的exec函数族可谓是无人不晓,它最著名的特性就是可以实现替换当前进程的地址空间,因此你如果在一个进程当中执行了exec,那 就不要指望exec返回执行exec调用点后面的操作了。exec并不负责创建进程,他只负责替换地址空间,负责创建进程的是由另一个系统调用来承担,就 是fork,所以在linux中典型的创建新的执行映像的方式就是fork+exec,当然在你不想要当前进程的情况下也可以直接exec。而在 windows下,exec却是简单的CreateProcess+ExitProcess的封装,在windows下一切最终都要落实到 win32API的,因此Win32API相当于多出来的一个层次,而不像linux直接进行系统调用完事,从这二者的实现我们可以看出什么端倪吗?
凡是用过unix的都知道unix的哲学,每次只做并且做好一件事情这个终极哲学,你看fork,连参数都没有,就是创建进程,再看exec,根本不管进 程的事,就是替换地址空间,只有这样,把如何组合的策略交给用户,用户才可以获得最大的自由,从而开发出丰富的应用程序。linux本身是一点策略都不提 供的,它不会帮你做你认为会省力的工作,也就是说,只要是你可以完成的工作它就绝对不插手,比如在不影响当前进程的情况下启动另一个进程,linux认为 没有必要直接提供这样一个系统调用,这里的用户指的是所有系统调用层上面的用户,包括库的设计者。库的设计者或者程序员用户可以随意组合这些现有的系统调 用接口,封装成更加方便的接口,只可惜操作系统并不会帮你,举个例子,fork+exec就有一个封装函数,叫做system。我们反过来看看 windows的策略,windows为了开发者可以最快的进行开发,另外加上它的内核和用户空间是比较同步的进行开发的,联系非常紧密,两个空间非常的 了解对方,因此windows往往会直接提供一些策略,这就增加了操作系统和开发者之间的耦合度,不像在linux下开发,系统调用接口很稳定,一般不怎 么变化,内核空间和用户空间只需要通过这个稳定的接口层通信就可以了,而且彼此完全可以不了解对方,正如我前一篇文章所说,这种特性带来的就是术业有专攻
的 庞大社区的支持,力量非常强大。既然windows提供了一些用户策略,那么它就明显不适合unix哲学同样是创建进程windows的 CreateProcess函数几乎为用户做完了全部的事情,包括创建进程,映射程序映像,这就是和linux的最大不同了。当然并不能说windows 不好,它也有自己的哲学,作为一个产品,它的开发者深知自己的产品,另外不管是内核还是用户空间策略都是产品的一部分,因此就没有必要区分那么清了,它的 开发者通过会议的方式进行协作,因此他们之间的通信就不一定要局限在系统调用接口了。
可能有些人会认为windows的exec的方式更加干净,确实有那么一点意思,linux的方式有些罗嗦也有那么一点意思,可是用户真的需要这种所谓的 干净吗?那要看用户是什么样的人了,信奉不同哲学的人往往会因为一点小的分歧大开杀戒。事实上linux的exec和windows的exec根本就不是 一个层面上的,在linux中,exec只是“创建进程”这件事情的“一部分”,而在windows下,exec却包含了“创建进程”这件事情,但是还不 止这件事情,另外还包括“退出当前进程”这件事情,用一句俗语区分它们就是,在linux中,exec的作用是“鸠占鹊巢”,在windows 中,exec的作用一个是“功成”另一个是“身退”。这里就可以看出linux和windows的设计粒度,显然linux更加细化一些,细化的东西组合 起来往往会出现规模效应,功能会很强大,而粗化的东西在扩展的时候功能会受到限制,比如linux可以很简单的实现“功成”+“身退”,就是 fork+exec+exit,其实就是三个只做一件事的系统调用之组合,反过来要在windows下实现“鸠占鹊巢”就不容易了,因此windows中 最细的东西都要比这个“鸠占鹊巢”要粗,于是就受到了限制。这样的话,在linux中就可以在保持pid不变的情况下重新启动自身,而在windows下 这个需求就很难了。
虽然同样都是exec函数,在linux和windows中的地位却大不相同,当然其位置也不同,在linux中可以很安心的将之放到系统调用门口,因为 它就做一件事,不会有任何副作用,但是在windows下,它的存在纯粹是为了兼容标准C,于是就要用Win32API来封装exec函数,而 Win32API中却没有替换地址空间这么细粒度的操作,于是乎只好仅仅实现语义,于是最终就有了CreateProcess+ExitProcess的 组合,有人可能会问这不也是一个组合吗?是的,这是一个组合,但是这是由只做一件事的函数作为元素组合的吗?显然不是。

你可能感兴趣的:(exec)