【Linux】进程地址空间的内核空间

简单来说,内核空间是操作系统内核在虚拟内存中的专属领地,它被系统中所有进程共享,但对用户程序来说是严格禁止访问的


什么是进程地址空间的内核空间?

当一个程序在操作系统中运行时,操作系统会为其创建一个进程,并给它一个假象:它拥有整个内存系统。这个假象就是进程地址空间(也叫虚拟地址空间)。

在32位系统中,这个空间是 0x000000000xFFFFFFFF,总共4GB的虚拟地址。操作系统通常会将这4GB的空间划分为两部分:

  • 用户空间 :下半部分(例如 0x000000000xC0000000,即0-3GB),供应用程序(如浏览器、文本编辑器)使用。

  • 内核空间 :上半部分(例如 0xC00000000xFFFFFFFF,即3-4GB),供操作系统内核使用。

注意:在64位系统中,地址空间巨大,划分方式类似,但用户空间和内核空间的边界位置不同,且都只使用地址总线支持的一部分位。

在电脑开机时,OS 是最先加载的软件,它的代码和数据存储在物理内存地址较低的地址,进程的内核空间在进行虚拟到物理的映射时,有一个专门的页表存储映射关系,叫内核级页表 。地址空间的用户空间在进行虚拟到物理的映射时,所使用的页表可以叫做用户页表。有多少个进程,就有多少个用户页表,但内核级页表只有一个,即所有进程共享一个内核级页表,因为所有进程的内核部分共享内核代码和数据。

用户程序如何与内核空间交互?

既然用户程序不能直接访问内核空间,那它如何请求操作系统服务(如打开文件、创建新进程)呢?答案是通过系统调用

过程如下:

  1. 用户态准备 :应用程序(用户态)调用C标准库函数,如 printf

  2. 陷入内核printf 内部会封装一个系统调用 (如 write),并通过特殊的CPU指令(如 int 0x80syscall)触发一个软中断或陷阱。

  3. 上下文切换 :CPU从用户态切换到内核态,并将执行权交给内核中预先定义好的系统调用处理程序。此时,处理器可以访问内核空间了。cpu 中有 ecs 寄存器,有两个比特位(00,01,10,11)标记当前 cpu 是处于用户态(11)还是内核态(00)可以通过 int 0x80 汇编指令将CPU从用户态切换到内核态,

  4. 内核处理:内核根据系统调用号,在内核空间中执行相应的代码,处理请求。

  5. 返回用户态 :内核处理完成后,再次执行特权指令,从内核态切换回用户态,并将结果返回给应用程序。

内核空间的关键特性

  • 高特权级

    这是最核心的安全机制。CPU提供了不同的特权级别 (Ring 0 到 Ring 3)。用户空间的程序运行在Ring 3 (用户态),权限最低。内核空间的代码运行在Ring 0(内核态),拥有最高的权限,可以执行任何CPU指令(如中断、内存管理指令),并能直接访问任何物理内存和硬件设备。

  • 所有进程共享同一份内核空间

    无论你打开了多少个程序(Chrome、Word、VS Code),它们各自的地址空间的用户部分是完全隔离的,但内核部分都映射到同一份物理内存。这样设计的好处是:

    • 效率:当一个进程发起系统调用(如读取文件)进入内核态时,无需切换页表,可以直接访问内核的数据结构,这是现代 OS 的做法,历史的 OS 要通过内核级页表(专门存储进程地址空间内核空间到物理内存的映射关系的页表)进行虚拟到物理的转换

    • 通信:进程间通信的某些机制(如共享内存)就是通过内核空间实现的。

  • 用户空间不可见、不可访问

    用户态程序无法直接读写内核空间的数据。如果尝试通过一个野指针访问内核地址(如 0xC0000000 以上的地址),CPU的内存管理单元会发现该访问来自用户态且目标地址是内核态,会立即触发段错误并终止程序,从而保护内核安全。

时钟中断

如果说内核空间是操作系统的"地盘",那么时钟中断就是驱动操作系统运转的"心跳"或"脉搏" 。它是一个定时器,以固定的频率打断当前正在执行的程序,强制将CPU控制权交还给内核。操作系统的本质:基于时钟中断的一个死循环


1. 什么是时钟中断?

时钟中断是由计算机硬件(通常是可编程间隔定时器)周期性产生的一种外部中断

  • 周期性:它就像一个精准的节拍器,每隔固定的时间(例如1毫秒,即1000Hz)就会触发一次。

  • 硬件触发:它不是由软件错误或指令引起的,而是由独立的硬件计时器向CPU发送一个电信号。

  • 抢占性:它的优先级非常高,无论CPU当前在做什么(运行用户程序,甚至执行内核的其他代码),一旦时钟中断信号到达,CPU通常会暂停当前任务,转而去执行中断处理程序。

2. 时钟中断的作用:操作系统的"脉搏"

时钟中断是操作系统能够实现多任务并发 和进行系统资源管理的基石。它的主要作用如下:

A. 实现进程调度(时间片轮转)

这是时钟中断最核心的功能。

  1. 时间片:操作系统为每个运行的进程分配一个固定长度的时间片(例如10毫秒或100毫秒)。这个时间片就是由时钟中断的"滴答"次数来计量的。

  2. 计时与中断:当一个进程开始运行时,内核会设置一个定时器。当该进程运行了例如100个"滴答"(时钟中断周期)后,下一个时钟中断到来。

  3. 强制切换:中断发生时,CPU强制从当前进程(无论它在做什么)跳转到内核预先设置好的时钟中断处理程序。

  4. 调度决策:内核的中断处理程序会检查当前进程的时间片是否用完。如果用完了,调度器(Scheduler)就会被唤醒,选择另一个优先级合适的进程运行。

  5. 上下文切换:内核保存当前进程的状态(寄存器、程序计数器等),加载新进程的状态,然后中断返回,CPU开始执行新进程。

这个过程就是我们常说的抢占式多任务。进程不是主动让出CPU的,而是被时钟中断这个"闹钟"强行叫停的。

B. 系统时间维护

时钟中断是操作系统感知"时间流逝"的基础。

  • 系统计时 :每次时钟中断触发,内核内部的计数器(如 jiffies)就加1。通过这个计数,操作系统可以计算出当前的系统时间、日期,以及文件的上次访问时间等。

  • 定时器管理 :应用程序或内核模块可以请求在未来某个时间点执行某项任务(如 sleep(1000))。内核会维护一个定时器队列,每次时钟中断时,都会检查是否有定时器到期,如果有,就执行其对应的回调函数。

C. 资源使用统计

时钟中断让操作系统能精确地"记账"。

  • 每次中断,内核都会记录这次中断发生在哪个进程的上下文中。

  • 通过累计,系统可以统计出每个进程消耗的用户态时间内核态时间 。这就是 top 或任务管理器里看到的CPU占用率的来源。

3. 时钟中断处理流程

当时钟中断信号到达CPU时,会发生以下一系列事件:

  1. 保存现场:CPU自动保存当前被中断进程的部分状态(如程序计数器)。随后,中断处理程序(汇编代码编写)会保存所有剩余的寄存器到当前进程的内核栈中。这是为了将来能准确恢复这个进程的运行。

  2. 执行中断服务例程:CPU根据中断向量表,找到并跳转到时钟中断对应的服务例程。这个例程是内核代码的一部分。

    • 它首先会更新系统时间(jiffies++)。

    • 它可能会减少当前进程的时间片计数器。

    • 它标记是否需要调度(例如,如果当前进程时间片归零)。

  3. 调用调度器 :如果判断需要调度,内核会调用 schedule() 函数。schedule() 会从所有就绪进程中选出一个最合适的。

  4. 上下文切换schedule() 执行实际的上下文切换,切换页表、用户栈、内核栈和寄存器等,让CPU准备运行新进程。

  5. 中断返回与恢复现场:最后,执行中断返回指令。这时,CPU已经指向了新进程,它会从新进程的内核栈中恢复其状态,然后继续执行该进程的用户态代码。

4. 时钟中断与虚拟内存的协同

结合之前聊的内核空间,可以更好地理解整个流程:

  • 中断发生 :CPU正在执行用户空间的代码(用户态)。

  • 进入内核 :中断迫使CPU切换到内核态 ,并使用当前进程的内核栈。此时,MMU仍然使用当前进程的页表,但由于所有进程的内核空间是共享映射的,内核代码可以无缝访问内核数据结构。

  • 切换进程:如果调度器决定切换到进程B,它会修改MMU中的页表基址寄存器,使其指向进程B的页表。

  • 返回用户态 :中断返回时,CPU切回用户态,开始执行进程B的用户空间代码。

总结

时钟中断是一个周期性的硬件信号,它赋予了操作系统抢占控制权的能力。它就像是操作系统的心脏,每一次跳动(中断)都驱动着系统去检查时间、统计资源,并做出关键的调度决策,从而实现了多个程序看似同时运行的效果,并保证了系统的响应性和公平性。

相关推荐
dustcell.2 小时前
高性能web服务器
android·服务器·前端
不知名。。。。。。。。2 小时前
Linux网络基础
运维·服务器·网络
2023自学中2 小时前
Linux 内核文件 rest_init 函数:流程与总结
linux·uboot
ZY小袁2 小时前
LVS(Linux virual server)实验
linux·运维·lvs
CN-David2 小时前
CentOS搭建Mycat中间件
linux·mysql·中间件·centos·mariadb
花间相见2 小时前
【Ubuntu实用工具】—— Fcitx5 输入法安装与完整配置指南(新手友好+避坑版)
linux·数据库·ubuntu
blockrock2 小时前
Linux Virtual Server (LVS)
linux·运维·lvs
蜡笔小炘2 小时前
Haproxy -- 高级功能配置及实用案例
linux·运维·服务器·haproxy
礼拜天没时间.2 小时前
Linux运维实战:巧用mv命令管理多版本Go环境,避免采坑
linux·运维·golang·centos