发新话题
打印

段寄存器的疑惑

段寄存器的疑惑

按照linuxkernel.net上走进内核 第四讲 的说法, 保护模式下 linux基本没有使用Intel cpu的段机制, 也没有使用ldt,那么cs,ds,ss等寄存器的作用似乎很小, 好像它们的值对每个应用程序都应该是一样的定值. 是这样的吗?
Linux is the future.
我试着运行的几个程序, 用gdb常看段寄存器的值,cs,ds,ss的值确实是确定的, 如下:
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
但问题是为什么是这些值?
Linux is the future.
引用:
原帖由 duncan 于 2008-5-31 00:34 发表
按照linuxkernel.net上走进内核 第四讲 的说法, 保护模式下 linux基本没有使用Intel cpu的段机制, 也没有使用ldt,那么cs,ds,ss等寄存器的作用似乎很小, 好像它们的值对每个应用程序都应该是一样的定值. 是这样的吗?
“从2.2版开始,Linux让所有的进程(或叫任务)都使用相同的逻辑地址空间”,所以对于各应用程序来说,段寄存器的值应该都是一样的。
但对于像wine这样模拟面向段的,windows下程序的应用程序,需要用到LDT,段寄存器中的值就可能会变化。

当然这些都是对于应用程序来说的。内核态下,段寄存器的内容当然和用户态下的不同。

正如“第四讲”中所说,段寄存器的作用虽小,但却不可省略,因为操作系统是运行在硬件的基础上的。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
引用:
原帖由 duncan 于 2008-5-31 01:46 发表
我试着运行的几个程序, 用gdb常看段寄存器的值,cs,ds,ss的值确实是确定的, 如下:
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
但 ...
段寄存器中的值只是“段选择符”。段选择符在描述符表中选中一个“段描述符”。段描述符描述了一个段。

先来看段选择符的结构:
bit15~bit3: 16位索引值得高位部分,低位为0。
bit2: TI位,选择描述符表,为0时代表索引值从GDT(全局描述符表)中进行选择。
bit1~bit0: RPL

再来看上面段寄存器中的值:
cs: 0000000001110 0 11
ss: 0000000001111 0 11
ds,es同ss

首先,一般的应用程序都使用GDT,所以TI位都为0。
Linux系统在安排GDT时,将用户代码段的描述符安排在了第14项,将用户数据段的描述符安排在了第15项。
又Linux把堆栈段当作数据段来处理,所以cs的索引部分为0xe。ss,ds,es的索引部分为0xf。
最后的RPL域,因为是应用程序是在用户态下,所以RPL值都为3。

这些值和“第四讲”中给出的不一样,是因为新的Linux内核改变了GDT中各描述符位置的安排。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

以上是我的看法,不对之处还请大家指正~
本帖最近评分记录
是这样的. 不过, 深入理解linux内核和走进内核-第四讲上的说法, 有如下定义:
#define __KERNEL_CS 0x10
#define __KERNEL_DS 0x18
#define __USER_CS 0x23
#define __USER_DS 0x2B
与上述定义不符, 把我搞的有点糊涂. 我查看了2.6.25的代码,结果是一样的.定义如下:
#define GDT_ENTRY_DEFAULT_USER_CS   14
#define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS * 8 + 3)

#define GDT_ENTRY_DEFAULT_USER_DS   15
#define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS * 8 + 3)

#define GDT_ENTRY_KERNEL_BASE   12

#define GDT_ENTRY_KERNEL_CS     (GDT_ENTRY_KERNEL_BASE + 0)
#define __KERNEL_CS (GDT_ENTRY_KERNEL_CS * 8)

#define GDT_ENTRY_KERNEL_DS     (GDT_ENTRY_KERNEL_BASE + 1)
#define __KERNEL_DS (GDT_ENTRY_KERNEL_DS * 8)
Linux is the future.
第四讲中给出的定义是之前老内核的定义。

2.6.25代码中,GDT表项的安排较“第四讲”的已经有了变化。

具体的值可能会随着不同的版本而变化,但产生该值的原理应该是不变的。
发新话题