一、概述
计算机系统三大部分:CPU 、内存、I/O。通常我们所写的程序都会加载到虚拟内存中,虚拟内存的大小是与CPU的位数有关,一般我们所用的计算机都是X86体系32位的linux操作系统,所以虚拟内存的大小是2^32 = 4G。我们一般把程序运行所需要的虚拟内存称为虚拟地址空间,它的大小也是4G,它又被分为用户空间(大小时3G)和内核空间(1G),那么它的构成是什么样的呢?
二、过程
程序的运行一般分为四个过程:预编译、编译、汇编、链接。
预编译阶段主要做:删除注释、处理以#开头的预编译指令,生成mian.i文件
编译阶段主要做:语义分析,代码优化,汇总所有的符号,生成main.s文件
汇编阶段主要做:把汇编指令转化为特定机器码,汇编指令一般有两种,inter X86体系和Linux 下的 AT&T,生成可重定位的obj文件。
链接阶段主要做:1、合并所有的obj文件的段,并调整段偏移和段长度,合并符号表,进行符号解析,分配虚拟地址空间。
2、连接的核心 符号表的重定向,生成二进制可执行文件。
符号解析:所以obj符号表中对符号引用的地方都要找到该符号定义的地方。
符号的重定向:在编译过程中产生的符号没有分配虚拟地址空间,重定向就是给重新符号表中没有分配虚拟地址空间的符号重新分配成符号的地址。也就是解析未定义的符号引用,将目标文件中的占位符替换为符号的地址,完成程序中各目标文件的地址空间的组织(重定位)
那么可执行文件的格式是什么样子呢?
多个文件进行编译,链接时生成的obj文件时,所有相同属性的段进行合并,组织在一个页面上。
重新调整调整段偏移和段长度,
合并符号表,进行符号解析,分配内存,
符号表的重定位,生成可执行文件。
程序的执行一般分为三步:
1.创建虚拟地址空间到物理内存的映射(创建内核地址映射结构体),创建页目录和页表。
2、加载数据段和代码段。
3、把可执行文件的入口地址放在CPU的PC寄存器中。
过程如图: