首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【linux学习指南】⽤户态和内核态的切换及切换流程

【linux学习指南】⽤户态和内核态的切换及切换流程

作者头像
学习起来吧
发布2025-01-01 08:45:13
发布2025-01-01 08:45:13
6320
举报
文章被收录于专栏:学习C/++学习C/++

📝⽤户态和内核态

CPU 指令集:是CPU实现软件指挥硬件执行的媒介,具体来说每一条汇编语句都对应了一条CPU 指令,而非常非常多的CPU 指令在一起,可以组成一个、甚至多个集合,指令的集合叫CPU 指令集。

CPU指令集有权限分级,大家试想,CPU 指令集可以直接操作硬件的,要是因为指令操作的不规范,造成的错误会影响整个计算机系统的。好比你写程序,因为对硬件操作不熟悉,导致操作系统内核、及其他所有正在运行的程序,都可能会因为操作失误而受到不可挽回的错误,最后只能重启计算机才行。

对开发人员来说是个艰巨的任务,还会增加负担,同时开发人员在这方面也不被信任,所以操作系统内核直接屏蔽开发人员对硬件操作的可能,都不让你碰到这些CPU 指令集。

针对上面的需求,硬件设备商直接提供硬件级别的支持,做法就是对CPU 指令集|设置了权限,不同级别权限能使用的CPU 指令集是有限的,以Inter CPU为例,Inter把 CPu 指令集操作的权限由高到低划为4级:

  • ring 0∶权限最高,可以使用所有CPu指令集
  • ring 1
  • ring 2
  • ring 3∶权限最低,仅能使用常规CPU 指令集,不能使用操作硬件资源的CPU指令集,比如工o读写、网卡访问、申请内存都不行

要知道的是,Linux系统仅采用ring0和ring 3这2个权限。CPU中有一个标志字段,标志着线程的运行状态,用户态为3,内核态为0。

  • ring 0被叫做内核态,完全在操作系统内核中运行。 执行内核空间的代码,具有ring 0保护级别,有对硬件的所有操作权限,可以执行所有(CPU指令集,访问任意地址的内存,在内核模式下的任何异常都是灾难性的,将会导致整台机器停机
  • ring3被叫做⽤⼾态,在应⽤程序中运⾏ 在用户模式下,具有ring 3保护级别,代码没有对硬件的直接控制权限,也不能直接访问地址的内存,程序是通过调用系统接口(System CallAPls)来达到访问硬件和内存,在这种保护模式下,即时程序发生崩溃也是可以恢复的,在电脑上大部分程序都是在,用户模式下运行的

低权限的资源范围较小,高权限的资源范围更大,所以用户态与内核态的概念就是CPU指令集权限的区别。 我们通过指令集权限区分用户态和内核态,还限制了内存资源的使用,操作系统为用户态与内核态划分了两块内存空间,给它们对应的指令集使用。

在内存资源上的使用,操作系统对用户态与内核态也做了限制,每个进程创建都会分配虚拟空间地址,以Linux32位操作系统为例,它的寻址空间范围是4G(2的32次方)﹐而操作系统会把虚拟控制地址划分为两部分,一部分为内核空间,另一部分为用户空间,高位的1G(从虚拟地址OxC0000000OxFFFFFFFF)由内核使用,而低位的 3G(从虚拟地址Ox00000000OxBFFFFFFF)由各个进程使用。

  • 用户态:只能操作0-3G范围的低位虚拟空间地址
  • 内核态:0-4G范围的虚拟空间地址都可以操作,尤其是对3-4G范围的高位虚拟空间地址必须由内核态去操作。
  • 3G-4G部分大家是共享的(指所有进程的内核态逻辑地址是共享同一块内存地址),是内核态的地址空间,这里存放在整个内核的代码和所有的内核模块,以及内核所维护的数据。
  • 在内核运⾏的过程中,会涉及内核栈的分配,内核的进程管理的代码会将内核栈创建在内核空间中,当然相应的⻚表也会被创建。

🌠 ⽤⼾态与内核态的切换

什么情况会导致⽤⼾态到内核态切换??

  • 系统调⽤:⽤⼾态进程主动切换到内核态的⽅式,⽤⼾态进程通过系统调⽤向操作系统申请资源完成⼯作,例如fork()就是⼀个创建新进程的系统调⽤。

操作系统提供了中断指令int0x80来主动进⼊内核,这是⽤⼾程序发起的调⽤访问内核代码的唯⼀⽅式。调⽤系统函数时会通过内联汇编代码插⼊int0x80的中断指令,内核接收到int 0x80中断后,查询中断处理函数地址,随后进⼊系统调⽤。

异常:当CPU在执行用户态的进程时,发生了一些没有预知的异常,这时当前运行进程会切换到处理此异常的内核相关进程中,也就是切换到了内核态,如缺页异常

中断:当CPU在执行用户态的进程时,外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU 会暂停执行下一条即将要执行的指令,转到与中断信号对应的处理程序去执行,也就是切换到了内核态。如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后边的操作等。

切换时CPU需要做什么??

当某个进程中要读写IO,必然会用到ring 0级别的CPU 指令集。而此时CPU的指令集操作权限只有ring 3,为了可以操作ring 0级别的CPU 指令集,CPU切换指令集操作权限级别为ring 0(可称之为提权),CPU再执行相应的ring 0级别的CPU指令集(内核代码)。

代码发生提权时,CPU是需要切换栈的!!前面我们提到过,内核有自己的内核栈。CPU切换栈是需要栈段描述符(ss寄存器)和栈顶指针(esp寄存器),这两个值从哪里来?。

  • CPU通过一个段寄存器(tr)确定TSS(任务状态段,struct TSS)的位置。在TSS结构中存在这么一个SSO和ESP0。提权的时候,CPU就从这个TSS里把SSO和ESPO取出来,放到ss和esp寄存器中。

🌉切换流程

  1. 从用户态切换到内核态时,首先用户态可以直接读写寄存器,用户态操作CPU,将寄存器的状态保存到对应的内存中,然后调用对应的系统函数,传入对应的用户栈地址和寄存器信息,方便后续内核方法调用完毕后,恢复用户方法执行的现场。
  2. 从⽤⼾态切换到内核态需要提权,CPU切换指令集操作权限级别为ring0。
  3. 提权后,切换内核栈。然后开始执⾏内核⽅法,相应的⽅法栈帧时保存在内核栈中。
  4. 当内核⽅法执⾏完毕后,CPU切换指令集操作权限级别为ring3,然后利⽤之前写⼊的信息来恢 复⽤⼾栈的执⾏。

从上述流程可以看出⽤⼾态切换到内核态的时候,会牵扯到⽤⼾态现场信息的保存以及恢复,还要进⾏⼀系列的安全检查,还是⽐较耗费资源的。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-12-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 📝⽤户态和内核态
  • 🌠 ⽤⼾态与内核态的切换
  • 🌉切换流程
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档