程序是如何成为进程?

    这是一个非常有意思的事情,一个存储在磁盘上的程序源码文件,如何一步步成为系统下面的一个进程?

    这里,我先分两个部分讲解:1.磁盘上的可执行文件-->进程;2.源码文件-->二进制可执行文件

    第一部分

        1.以unix系统为例。当我们在shell下执行一个磁盘上的可执行文件时(ELF),如下

            unix>./prog

            这里,shell会生成一个子shell进程(fork)。子进程通过execve系统调用启动加载器。加载器删除子进程现有的虚拟存储器段,在可执行文件(ELF)中段头部表的指导下,创建并初始化一组新的代码,数据,栈和堆段。新的栈和堆被初始化为零,通过虚拟地址空间中的页映射到可执行文件的页大小的片,新的代码和数据段被初始化为可执行文件的内容。最后加载器跳转到ctrl.o初执行程序的初始化工作,然后是进入main函数开始应用程序的执行-->程序就是这样变成了进程。在加载器的帮助下,程序跑进了一个进程中,然后开始了自己的进程路。

        2.此处,有两对概念需要了解清楚:1.程序和进程;2.fork和execve;

           2.1.程序,是一堆代码和数据。程序可以作为目标模块存在于磁盘上,或者作为段存在于地址空间中。

                进程,是执行中程序的一个具体实例。程序总是运行在某个进程的上下文中(上下文,可以简单理解为一个进程运行是的所有状态参数)。

           2.2.fork函数在新的子进程中运行相同的程序,新的子进程是父进程的一个复制品。

                execve函数在当前进程的上下文加载并运行一个新的程序。它会覆盖当前进程的地址空间,但并没有创建新的进程。新的程序仍然有相同的PID,并且继承了调用execve函数时已经打开的所有fd(文件描述符)。

    第二部分

        1.相对于静态链接产生的可执行文件,大多数程序员现在开发的程序都是动态链接的可执行文件。这里简单说明一下动态链接的可执行文件。

            当动态链接的可执行文件运行时(即从程序-->进程时),同样会经过一个如上面描述的步骤,然而动态链接的可执行文件包含一个.interp节,此时加载器会注意到这个节,同时会将动态链接器加载到内存中。剩下的工作将交由这个链接器来完成。链接器会重定位文件对共享库符号的引用,生成一个存储器中完全链接的可执行文件-->自此,一个完整的可执行文件,产生了。它可以执行并成为一个进程了。


你可能感兴趣的:(进程,程序,fork,链接器,execve)