Linux 存储管理3——地址映射全过程

简介: 假定一条程序已经运行,整个映射机制都已建立好,并且cpu正在执行main()中的:call 08048368 这条指令,要转移到虚拟地址0x08048368去。接下来我们分析整个地址映射的过程: 首先是段式映射阶段。

假定一条程序已经运行,整个映射机制都已建立好,并且cpu正在执行main()中的:call 08048368 这条指令,要转移到虚拟地址0x08048368去。接下来我们分析整个地址映射的过程:

首先是段式映射阶段。由于地址0x08048368是一个程序的入口,更重要的是在执行的过程中是由cpu中的“指令指针寄存器(用于存储下次将要执行的指令在代码段中的偏移量)”EIP所指向的代码段中。因此i386 CPU使用代码段寄存器CS的当前值来作为段式映射的“选择码”,也就是用它作为在段描述表中的下标。

什么是段描述表呢?什么是全局段描述表GDT?什么是局部段描述表LDT?

我们先回顾一下保护模式下段寄存器的格式:


也就是说,bit2(TI=Table Indicator:指示器)为0时表示用GDT,为1时表示用LDT。intel的设计意图是内核用GDT而各个进程都用其自己的LDT,最后两位RPL为所要求的特权级别,分为4个级别,0为最高级。(一般内核为0级,用户未3级)

现在可以来看看CS的内容了,内核在建立一个进程时都要将其段寄存器设置好,有关代码如下:


这里reg->xds 是段寄存器DS的映像,一次类推,这里可以看到一个有趣的事,就是除了CS被置成USER_CS之外,其他所有的段寄存器都设置成USER_DS,你看,比如堆栈寄存器SS,也被设置成了USER_DS,这说明了什么呢?这说明:虽然Intel的意图是将一个进程映像分成代码段、数据段、和堆栈段,但是,linux内核却并不买这个帐,在linux中堆栈段和数据段式不分的。

上面说寄存器的映像,被设置成了USER_CS和USER_DS到底是什么:


也就是说,Linux内核中只使用四种不同的段寄存器数值,两种用于内核本身,两种用于所有的进程。现在我们讲这四种数值用二进制展开并与段寄存器的格式相对照:


首先TI都是0,也就是说全部使用GDT。这就与Intel的设计意图不一致了。实际上,在Linux内核中基本上不使用局部段描述表LDT。LDT只是在VM86模式中运行wine以及其它在Linux上模拟Windows软件或DOS软件的程序中才使用。

再看RPL,只用了0和3两级,内核为0级而用户(进程)为3级。

回到我们的程序中。我们的程序显然不是内核程序,所以在进程的用户空间运行,内核在调度该进程进入运行时,把CS设置成_USER_CS即0x23。所以,CPU以4为下标,从全局扫描表GDT中找对应的段描述项








相关文章
|
1月前
|
存储 缓存 Linux
如何在Linux环境下对pip的缓存地址进行修改
如何在Linux环境下对pip的缓存地址进行修改
|
存储 编译器
Linux--程序地址空间
Linux--程序地址空间
|
2月前
|
存储 Linux
Linux下的系统编程——共享存储映射(十)
Linux下的系统编程——共享存储映射(十)
31 1
Linux下的系统编程——共享存储映射(十)
|
1月前
|
Linux Shell C语言
【Shell 命令集合 设备管理 】Linux 设置键盘映射表 loadkeys命令 使用指南
【Shell 命令集合 设备管理 】Linux 设置键盘映射表 loadkeys命令 使用指南
36 0
|
3月前
|
存储 关系型数据库 MySQL
Linux C/C++ 开发(学习笔记八):Mysql数据库图片存储
Linux C/C++ 开发(学习笔记八):Mysql数据库图片存储
50 0
|
3月前
|
存储 Linux 虚拟化
Linux和开源存储
Linux和开源存储
Linux和开源存储
|
1月前
|
存储 算法 Shell
【Shell 命令集合 设备管理 】Linux 显示当前系统中定义的键盘映射表 dumpkeys命令 使用指南
【Shell 命令集合 设备管理 】Linux 显示当前系统中定义的键盘映射表 dumpkeys命令 使用指南
31 0
|
19天前
|
Linux 编译器 Windows
【Linux】10. 进程地址空间
【Linux】10. 进程地址空间
19 4
|
1月前
|
网络协议 Linux C++
Linux C/C++ 网络编程中地址格式转换(inet_pton和inet_ntop函数)
Linux C/C++ 网络编程中地址格式转换(inet_pton和inet_ntop函数)
26 0
|
1月前
|
存储 Linux 程序员
【Linux】—— 进程地址空间
【Linux】—— 进程地址空间