《Linux内核设计的艺术:图解Linux操作系统架构设计与实现原理》——2.14 进程0由0特权级翻转到3特权级,成为真正的进程

本文涉及的产品
网络型负载均衡 NLB,每月750个小时 15LCU
应用型负载均衡 ALB,每月750个小时 15LCU
公网NAT网关,每月750个小时 15CU
简介: 本节书摘来自华章计算机《Linux内核设计的艺术:图解Linux操作系统架构设计与实现原理》一书中的第2章,第2.14节,作者:新设计团队著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.14 进程0由0特权级翻转到3特权级,成为真正的进程

Linux操作系统规定,除进程0之外,所有进程都要由一个已有进程在3特权级下创建。在Linux 0.11中,进程0的代码和数据都是由操作系统的设计者写在内核代码、数据区,并且,此前处在0特权级,严格说还不是真正意义上的进程。为了遵守规则,在进程0正式创建进程1之前,要将进程0由0特权级转变为3特权级。方法是调用move_to_user_mode()函数,模仿中断返回动作,实现进程0的特权级从0转变为3。
执行代码如下:

//代码路径:init/main.c:
void main(void)
{
    …
    move_to_user_mode();
    …
}

//代码路径:include/system.h:    //参看1.3.4节
#define move_to_user_mode() \    //模仿中断硬件压栈,顺序是ss、esp、eflags、cs、eip
__asm__("movl %%esp,%%eax\n\t" \    
         "pushl $0x17\n\t" \    //SS进栈,0x17即二进制的10111(3特权级、LDT、数据段)
         "pushl %%eax\n\t" \     //ESP进栈
         "pushfl\n\t" \        //EFLAGS进栈    
         "pushl $0x0f\n\t" \    //CS进栈,0x0f即1111(3特权级、LDT、代码段)
         "pushl $1f\n\t" \    //EIP进栈
         "iret\n" \        //出栈恢复现场、翻转特权级从0到3
         "1:\tmovl $0x17,%%eax\n\t" \    //下面的代码使ds、es、fs、gs与ss一致
               "movw %%ax,%%ds\n\t" \
               "movw %%ax,%%es\n\t" \
               "movw %%ax,%%fs\n\t" \
               "movw %%ax,%%gs" \
            :::»ax»)

IA-32体系结构翻转特权级的方法之一是用中断。第1章介绍过,当CPU接到中断请求时,能中断当前程序的执行序,将CS:EIP切换到相应的中断服务程序去执行,执行完毕又执行iret指令返回被中断的程序继续执行。
这期间,CPU硬件还做了两件事:一件是硬件保护现场和恢复现场,另一件是可以翻转特权级。
从代码的执行序上看,中断类似函数调用,都是从一段正在执行的代码跳转到另一段代码执行,执行之后返回原来的那段代码继续执行。为了保证执行完函数或中断服务程序的代码之后能准确返回原来的代码继续执行,需要在跳转到函数或中断服务程序代码之前,将起跳点的下一行代码的CS、EIP的值压栈保存,保护现场。函数或中断服务程序的代码执行完毕,再将栈中保存的值出栈给CS、EIP,此时的CS、EIP指向的就是起跳点的下一行,恢复现场。所以,CPU能准确地执行主调程序或被中断的程序。实际需要保护的寄存器还有EFLAGS等。
中断与函数调用不同的是,函数调用是程序员事先设计好的,知道在代码的哪个地方调用,编译器可以预先编译出压栈保护现场和出栈恢复现场的代码;而中断的发生是不可预见的,无法预先编译出保护、恢复的代码,只好由硬件完成保护、恢复的压栈、出栈动作。所以,int指令会引发CPU硬件完成SS、ESP、EFLAGS、CS、EIP的值按序进栈,同理,CPU执行iret指令会将栈中的值自动按反序恢复给这5个寄存器。
CPU响应中断的时候,根据DPL的设置,可以实现指定的特权级之间的翻转。前面的sched_init函数中的set_system_gate(0x80,&system_call)就是设置的int 0x80中断由3特权级翻转到0特权级,3特权级的进程做了系统调用int 0x80,CPU就会翻转到0特权级执行系统代码。同理,iret又会从0特权级的系统代码翻转回3特权级执行进程代码。
move_to_user_mode()函数就是根据这个原理,利用iret实现从0特权级翻转到3特权级。
由于进程0的代码到现在一直处在0特权级,并不是从3特权级通过int翻转到0特权级的,栈中并没有int自动压栈的5个寄存器的值。为了iret的正确使用,设计者手工写压栈代码模拟int的压栈,当执行iret指令时,CPU自动将这5个寄存器的值按序恢复给CPU,CPU就会翻转到3特权级的段,执行3特权级的进程代码。
为了iret能翻转到3特权级,不仅手工模拟的压栈顺序必须正确,而且SS、CS的特权级还必须正确。注意:栈中的SS值是0x17,用二进制表示就是00010111,最后两位表示3,是用户特权级,倒数第3位是1,表示从LDT中获取段描述符,第4~5位的10表示从LDT的第3项中得到进程栈段的描述符。
当执行iret时,硬件会按序将5个push压栈的数据分别出栈给SS、ESP、EFLAGS、CS、EIP。压栈顺序与通常中断返回时硬件的出栈动作一样,返回的效果也是一样的。
执行完move_to_user_mode( ),相当于进行了一次中断返回,进程0的特权级从0翻转为3,成为名副其实的进程。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
相关文章
|
2月前
|
监控 Linux 开发者
理解Linux操作系统内核中物理设备驱动(phy driver)的功能。
综合来看,物理设备驱动在Linux系统中的作用是至关重要的,它通过与硬件设备的紧密配合,为上层应用提供稳定可靠的通信基础设施。开发一款优秀的物理设备驱动需要开发者具备深厚的硬件知识、熟练的编程技能以及对Linux内核架构的深入理解,以确保驱动程序能在不同的硬件平台和网络条件下都能提供最优的性能。
120 0
|
5月前
|
并行计算 Linux
Linux内核中的线程和进程实现详解
了解进程和线程如何工作,可以帮助我们更好地编写程序,充分利用多核CPU,实现并行计算,提高系统的响应速度和计算效能。记住,适当平衡进程和线程的使用,既要拥有独立空间的'兄弟',也需要在'家庭'中分享和并行的成员。对于这个世界,现在,你应该有一个全新的认识。
236 67
|
4月前
|
Web App开发 Linux 程序员
获取和理解Linux进程以及其PID的基础知识。
总的来说,理解Linux进程及其PID需要我们明白,进程就如同汽车,负责执行任务,而PID则是独特的车牌号,为我们提供了管理的便利。知道这个,我们就可以更好地理解和操作Linux系统,甚至通过对进程的有效管理,让系统运行得更加顺畅。
113 16
|
4月前
|
Unix Linux
对于Linux的进程概念以及进程状态的理解和解析
现在,我们已经了解了Linux进程的基础知识和进程状态的理解了。这就像我们理解了城市中行人的行走和行为模式!希望这个形象的例子能帮助我们更好地理解这个重要的概念,并在实际应用中发挥作用。
92 20
|
3月前
|
监控 Shell Linux
Linux进程控制(详细讲解)
进程等待是系统通过调用特定的接口(如waitwaitpid)来实现的。来进行对子进程状态检测与回收的功能。
73 0
|
3月前
|
存储 负载均衡 算法
Linux2.6内核进程调度队列
本篇文章是Linux进程系列中的最后一篇文章,本来是想放在上一篇文章的结尾的,但是想了想还是单独写一篇文章吧,虽然说这部分内容是比较难的,所有一般来说是简单的提及带过的,但是为了让大家对进程有更深的理解与认识,还是看了一些别人的文章,然后学习了学习,然后对此做了总结,尽可能详细的介绍明白。最后推荐一篇文章Linux的进程优先级 NI 和 PR - 简书。
101 0
|
3月前
|
存储 Linux Shell
Linux进程概念-详细版(二)
在Linux进程概念-详细版(一)中我们解释了什么是进程,以及进程的各种状态,已经对进程有了一定的认识,那么这篇文章将会继续补全上篇文章剩余没有说到的,进程优先级,环境变量,程序地址空间,进程地址空间,以及调度队列。
64 0
|
3月前
|
Linux 调度 C语言
Linux进程概念-详细版(一)
子进程与父进程代码共享,其子进程直接用父进程的代码,其自己本身无代码,所以子进程无法改动代码,平时所说的修改是修改的数据。为什么要创建子进程:为了让其父子进程执行不同的代码块。子进程的数据相对于父进程是会进行写时拷贝(COW)。
66 0
|
5月前
|
缓存 运维 前端开发
|
5月前
|
缓存 运维 前端开发
阿里云操作系统控制台:高效解决性能瓶颈与抖动之进程热点追踪
遇到“进程性能瓶颈导致业务异常”等多项业务痛点时,提供高效解决方案,并展示案例。