概述
Linux下C程序生成主要由四个步骤组成:预编译、编译、汇编、链接。编译器gcc经过预编译、编译、汇编3个步骤将源程序文件转换成目标文件。如果程序有多个目标文件或程序中使用了库函数,则编译器还需要将所有目标文件及所需的库文件链接起来,最后生成可执行程序。当程序执行时,操作系统将可执行程序复制到内存中,程序转为为进程通常需要以下步骤:
*内核将程序读入内存,为程序分配内存空间;
*内核为该进程分配进程标识符PID及其他所需资源;
*内核为该进程保存PID及相应的状态信息,把进程放到运行队列中等待执行。程序转化为进程后就可被操作系统的调度程序执行了。
进程的内存映像是指内核在内存中如何存放可执行程序文件。在将程序转化为进程的过程中,操作系统将可执行程序从硬盘复制至内存中,其布局如下:
高端地址
+++++++++++++++++++++++
+命令行参数及环境变量
+++++++++++++++++++++++
+栈
+
+堆
+++++++++++++++++++++++
未被初始化数据段
++++++++++++++++++++++
数据段
++++++++++++++++++++++
代码段
++++++++++++++++++++++
低端地址
其中:
*代码段:即二进制机器代码,代码段是只读的,可被多个进程共享。比如一个进程创建了一个子进程,父子进程共享代码段,此外子进程还获得父进程数据段、堆、栈的复制。
*数据段:存储已经被初始化的变量,包括全局变量和已被初始化的静态变量;
*未初化数据段:存储未被初始化的静态变量,也被称为BSS段;
*堆:用于存放程序运行中动态分配的变量;
*栈:用于函数调用,保存函数返回地址、函数参数、函数内部定义的局部变量。
此外,高地址还存储了命令行参数与环境变量。
可执行程序与内存映像的不同之处在于:可执行程序位于磁盘中而内存映像位于内存;可执行程序没有堆栈,因为程序被加载到内在中才会分配堆栈;可执行程序虽然也有未初始化数据段但它并不被存储在位于硬盘中的可执行文件中;可执行程序是静态的、不变的,而内在映像随着程序的执行是在动态变化的,比如数据段随着程序的执行要存储新的变量值,栈在函数调用时也是不断在变化中。
Linux下程序转化成进程的详细步骤:
1) 内核将程序读入内存,并为程序分配一定的内存空间;
2) 内核为进程分配一个PID,还有其他一些相关资源;
3) 内核为进程保存PID和相应的状态信息,把进车功能放入到运行队列中等待运行。
基本上也就这3个步骤了。下面顺便记记进程的内存映像:
首先,什么叫做内存映像呢? 进程的内存映像,指的是内核在内存中如何存放可执行程序文件。注意了,这里的可执行程序文件和内存映像是有区别的,,具体是:
1) 可执行程序是位于硬盘上的,而内存映像位于内存上;
2) 可执行程序没有堆栈,因为只有当程序被加载到内存上的时候才会分配相应的堆栈
3) 可执行程序是静态的,因为它还没运行,但是内存映像是动态的,数据是随着运行过程改变的;
尽管程序映像看起来占据了一个连续的内存块,但实际上,操作系统将程序映像映射到不一定连续的物理内存块中。通常的映射将程序映像划分成大小相同的片,这些片被称为页(PAGE)。操作系统将这些页加载到内存中,当处理器引用某页上的内存时,操作系统会从一个表中查找这一页的物理位置。这种映射方式允许栈和堆有很大的逻辑地址空间,除非需要,否则这些栈和堆实际上可以不占用物理内存。操作系统隐藏了这种底层映射的存在,这样,即使有些页实际上并没有驻存在内存中,程序员也可以认为程序映像在逻辑上是连续的。
注:堆是由malloc函数分配到,栈是由操作系统分配的。
最后
以上就是温婉百褶裙为你收集整理的Linux程序映像的布局的全部内容,希望文章能够帮你解决Linux程序映像的布局所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复