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指令返回程序还是在原来的位置,这段代码也就假装一个进程的切回,在内部把内核态改为了用户态
引用
数据访问只能高特权级访问低特权级,代码跳转只能同特权级跳转,要想实现特权级转换,可以通过中断和中断返回来实现。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)