首先抛两个话题:

(1)ELF文件有分段,linux内存有分段机制,这儿意指哪个?两个分段有什么关联

(2)常有人提到linux不使用分段机制,是什么个情况?

 

关于第一个问题,ELF文件的分段,更多的是从功能和属性来做区分,是在文件区段上的划分;内存的分段机制是针对内存布局的划分;这两者本来没有必然的联系,ELF文件中的某个段可以加载到内存的任意段中,加载到内存的任何位置。为什么会产生这么混淆的理解呢,我想是因为内存的分段和文件分段都存在例如代码段数据段这些概念,而且也的确是根据相应的段寄存器进行寻址。在现代linux的体系架构中,代码段和数据段拥有相同的基地址和段长度。

 

再说linux不使用分段机制的问题

首先,linux不使用段基址是因为有很多体系结构的CPU不支持分段机制,由于i386系列的历史演变过程,它对页式存储管理的支持是在其段式存储管理已经存在了相当长的时间以后才发展起来的。所以,不管程序是怎样写的,i386 CPU一律对程序中使用的地址先进行段式映射,然后才能进行页式映射。所以,在i386系列中,linux还是象征性的使用了分段机制。

在之前的实模式中编程中,利用段寄存器和偏移量寻址,段寄存器中存储了段基址;在保护模式中,仍然要使用段寄存器,只不过段寄存器存储的是段选择符,段选择符配合段描述符表寄存器,可将逻辑地址转换为线性地址。

对i386系列,linux也没有将寻址完全建立在分段上,linux使用了分段,但是仅仅使用代码段和数据段进行寻址代码和数据的寻址,另又分为用户段和内核段,所以一共只使用了4种段类型。这四种段都从相同的段基址0开始,描述0到4G的整个地址空间,也就是说经过这些段地址描述符映射后的地址与映射前保持原值不变

现代CPU可使用保护模式编程,所谓保护模式当然是可以起到“保护”作用,在linux中,对这种保护作用主要使用了特权级别的保护,更多更细粒度的保护依赖于分页机制。

linux对数据和代码寻址,仍然要使用的段寄存器,只不过由于之前所说的,代码和数据段从相同的起始地址开始,所以最后逻辑地址转换成线性地址之后在同一个线性地址空间中,再利用分页机制的线性地址到物理地址转换即可完成寻址,而线性地址到物理地址的转换是机械的工作,很容易完成。另有一说,linux下逻辑地址即可认为是线性地址,也可以这么理解,因为代码段和数据段从相同的基地址开始