日期:2014-05-16  浏览次数:20687 次

新进程是怎样被加载运行的
对于"可执行映像文件的内容替换它正执行的 s h e l l二进制映像"这种说法,我不太理解,为什么要这样做啊,shell直接把可执行文件加载到进程中运行不就可以了,干嘛还要先克隆个自身,再替换自身。

------解决方案--------------------
假设你shell下执行 cat /proc/cpuinfo | grep xxx
shell检测到第一个命令cat后,不用fork,即不拷贝shell自己的代码,直接用cat的代码替换掉shell进程,那么这个进程就只有cat的功能。管道| 和 后面的grep就无法执行了,因为cat并没有这些功能。处理管道定向以及再启动多个命令都是shell的功能。
所以shell要一直存在并控制全局,所以要fork备份自己,创建子进程去执行具体的命令,父进程还是shell
------解决方案--------------------
没有理解linux里程序运行的原理才有这样的疑惑

首先,linux内核在启动完成后,就不再主动运行了。就相当于驻留在内存里的一段代码,只有各个进程需要调用内核的服务时候才会运行(就是系统调用),以及发生中断的时候才会运行。
所以创建子进程的动作是应用程序主动发起的,内核只是提供创建子进程的服务,内核不会主动创建子进程的。

然后就是为什么要先克隆,再创建。这是linux内核提供的创建进程的步骤。一般我们的理解,创建子进程,内核就完全从头开始构建子进程:分配对应的数据结构,把程序从磁盘装入相应的内存... ,这样的做法也是最合理的。
但是从头创建一个进程内核需要为这个进程产生很多数据结构的分配和初始化,这个过程很消耗cpu资源。如果从一个已经存在的进程结构入手,先创建一个进程的拷贝,再修改这个拷贝,装入新的程序,就能大大提高效率。所以先拷贝再装入程序的方法创建子进程,是为了提高效率。

你说的“管道| 和 后面的grep就无法执行了”,shell常驻内存的,它会根据管道后面的命令来处理grep的
------------------------------
一个进程同时只能装入一个程序的代码(不同的时间可以是不同的程序的代码,例如clone),所以你既然说shell要常驻内存,那么就一定会占据一个进程的代码段内存。所以需要创建子进程执行具体的命令。