linux-0.11分析:init文件 main.c的从内核态到用户态,move_to_user_mode() 第十一篇随笔

12、从内核态到用户态,move_to_user_mode()

参考 [github这个博主的 厉害][ https://github.com/sunym1993/flash-linux0.11-talk ]

从函数的名称就可以看出来,切换到用户模式

那么怎么才能表示是内核态和用户态,就要用到之前的一个段选择子,之前段选择子是为了法段机制,

里面高13位存的描述符索引,

第3位(TI)表示从哪个全局描述符(GDT)还是局部描述符(LDT)寻找,

最后2位(RPL)表示特权级

直接在看看图吧(段选择子一般是ds,cs,ss之类的)

接下来看看move_to_user_mode这个函数

include文件 -> asm文件 -> system.h

#define move_to_user_mode() \
__asm__ ("movl %%esp,%%eax\n\t" \
	"pushl $0x17\n\t" \
	"pushl %%eax\n\t" \
	"pushfl\n\t" \
	"pushl $0x0f\n\t" \
	"pushl $1f\n\t" \
	"iret\n" \
	"1:\tmovl $0x17,%%eax\n\t" \
	"movw %%ax,%%ds\n\t" \
	"movw %%ax,%%es\n\t" \
	"movw %%ax,%%fs\n\t" \
	"movw %%ax,%%gs" \
	:::"ax")

很明显这又是一段内嵌汇编,烦死了那就慢慢看吧

pushl $0x17 是在给SS赋值

0x17 二进制 0001 0111

最后2位(RPL)为11 也就是3 位表示为用户态

第3位(TI)为1 表示从局部描述符(LDT)中寻找

pushl $0x0f 是在给CS辅助

0x0f 二进制 0000 1111

最后2位(RPL)为11 也就是3 位表示为用户态

第3位(TI)为1 表示从局部描述符(LDT)中寻找

还是看看GDT和LDT那个图吧

iret 最后通过iret指令返回程序还是在原来的位置,这段代码也就假装一个进程的切回,在内部把内核态改为了用户态

引用

数据访问只能高特权级访问低特权级,代码跳转只能同特权级跳转,要想实现特权级转换,可以通过中断和中断返回来实现。

posted @ 2022-08-12 13:04  水三丫  阅读(138)  评论(0编辑  收藏  举报