文章目录
- 用户态与内核态
- 进程地址空间
- 操作系统的本质
- 信号的处理时机
用户态与内核态
进程在执行代码的过程中代码必定涉及用户代码,库函数代码及操作系统内核代码;
以简单的printf()
函数为例,该函数必定为先执行用户的代码即知道需要调用printf()
函数,再执行库(如libc
)中的代码printf()
最后该函数必定封装了操作系统的系统调用接口(如write()
)一系列的操作;
这意味着进程必须要由用户态转换为内核态,再由内核态转换回用户态才有对应的"权限"执行对应的接口;
当执行系统调用接口时操作系统将对进程进行用户切换,即用户态转换为内核态或是内核态转换为用户态;
-
用户态(User Mode)
-
访问限制
在用户态运行的进程只能访问它自己的用户空间代码和数据;这是为了保护系统安全,防止用户程序意外或故意地修改系统关键数据;
-
受限访问内核资源
用户态进程无法直接访问操作系统内核代码和数据,也不能执行特权指令(如直接操作硬件或更改系统设置);
-
系统调用
当用户态进程需要请求内核服务时(例如文件操作、网络通信等),它通过系统调用(如
int 0x80
在x86 Linux系统上)请求操作系统来执行这些操作;系统调用是用户态与内核态通信的一种受控机制;
-
-
内核态(Kernel Mode)
-
完全访问权限
在内核态运行的代码有权访问系统的所有资源,包括所有内存、硬件设备和CPU指令集;这包括内核空间的代码和数据,也包括可能的用户空间数据(用于完成用户的请求);
-
保护机制
尽管内核态有更高的权限,操作系统通过严格的权限管理和进程隔离机制,确保用户进程只能通过合法的系统调用接口访问内核资源;
-
进程地址空间
每个进程都存在一个对应的内核数据结构task_struct
,该数据结构保存了进程的各种属性,其中存在一个进程地址空间作为虚拟地址;
虚拟地址通过页表映射至物理地址;
其中进程地址空间中0-3GB
为用户空间,3-4GB
为内核空间;
对于用户而言所使用的进程地址空间为用户空间,通过页表与MMU
内存管理单元访问对应位置的物理内存;
本质上页表存在两种页表分别为用户级页表与内核级页表;
-
用户级页表
管理进程的用户地址空间,主要用于映射用户代码和数据所需的物理内存;
由于进程具有独立性,用户级页表的数量为当前进程的数量,即一个进程有一个独立的用户级页表;
-
内核级页表
管理内核空间地址,映射内核代码和数据所需的物理内存;
内核地址空间在所有进程中是共享的,因此内核级页表在所有进程中是相同的,意味着系统中只有一个内核级页表;
本质上用户级页表与内核级页表的结构是统一的,只是在逻辑上进行分开;
用户空间通过用户级页表访问物理内存,内核空间通过内核级页表访问操作系统内核代码和数据,保证了进程的隔离和内核的安全性;
-
进程视角
在进程视角中本质上就是调用自己的地址空间;
-
操作系统视角
操作系统视角为任何一个时期都将有进程执行;
用户级页表与内存级页表本质上属于一种数据结构的实例化,其可以属于一种数据具有自己的地址;
-
CR3
寄存器在
CPU
中存在一个寄存器为CR3
,该寄存器存储着页表的地址;当进程需要执行自己用户的代码数据时,即访问用户级地址空间时,
CR3
寄存器指向用户级页表的地址; -
ecs
寄存器在
CPU
中还存在一个ecs
寄存器,该寄存器中存在两个以比特位形式表现的标志位;其四种选项分别为
00
,01
,10
,11
;其中
11
表示为用户态,00
表示为内核态;其标定了一个用户态与内核态的权限,当其标志位变为
00
时表示其陷入内核;该寄存器也提供了一个接口以便能够修改对应的标志位;
故当使用汇编语句
int 80
时即标志位变为00
从而陷入内核;
操作系统的本质
操作系统可以理解为一个软件,一个进程;
其本质上是一个基于硬件中断的死循环,其中发生中断的可以是计算机组成中的各个硬件;
这个循环不断地等待和处理中断信号,中断可以来自各种硬件设备或软件事件;
这些中断不限于I/O
中断,系统调用中断,异常中断等;
当不存在I/O
中断,系统调用中断,异常中断等中断时,必须通过一种措施使操作系统持续的调度不同的进程以维持自身的系统维护和进程调度;
该措施为 时钟中断 ,其中断是由计算机组成中的 时钟芯片 产生的;
-
时钟芯片
时钟芯片是一种专门用于生成时钟信号的硬件装置;
其提供了一个稳定的时钟源以保持系统时间,计时以及产生时间中断;
在进行时间中断时其将以非常短的时间向操作系统发送一个硬件中断异常以维持系统的维护和进程调度;
-
时钟中断
时钟中断是由时钟芯片产生的一种中断信号;
其以周期性的发生,用于告诉操作系统当前时间的变化或需要执行定时任务;
时钟中断通常用于多任务操作系统中以实现进程调度,系统计时等功能;
操作系统的基本工作机制可以分为主循环,等待中断,中断处理;
-
主循环
操作系统在启动时进入一个主循环,这个主循环负责监控和管理系统资源,响应外部和内部事件;
-
等待中断
在主循环中,操作系统通常处于等待中断的状态;
这个中断状态可以来自硬件(时钟中断,
I/O
中断等); -
中断处理
当一个中断发生时,操作系统将暂停正在进行的工作,跳转到响应的中断处理程序;
这些中断处理程序执行特定的任务,例如更新系统时间,处理
I/O
请求,调度新进程等;
时钟中断在操作系统中十分重要,其负责定时中断,进程调度,系统计时,定时任务等;
-
定时中断
时钟芯片周期性地产生时钟中断(例如每秒
100
次);每次时钟中断发生时操作系统会执行中断处理程序以保证就算不发生其他中断操作系统也能够进行进程调度,系统维护等操作;
-
进程调度
时钟中断触发进程调度器的运行;
调度器决定是否需要切换当前运行的进程以确保所有进程都能够得到
CPU
时间,这就是所谓的"时间片轮转调度"; -
系统计时
操作系统使用时钟中断来保持系统时间的准确性;
每次中断发生时操作系统会更新其内部计时器;
-
定时任务
操作系统可以设置定时器,在指定的时间后产生中断以执行某些定时任务;
这些任务包括系统维护,资源回收,性能监控等;
/* 简化的操作系统模型 */
while (true) {
wait_for_interrupt(); // 等待中断
handle_interrupt(); // 处理中断
}
实际上在操作系统中以for (;;) { pause(); }
的形式存在;
-
pause()
的作用-
等待中断
pause()
指令使CPU
进入低功耗状态等待中断发生; -
处理中断
当中断发生时,
CPU
会跳转到响应的中断处理程序执行特定任务; -
恢复主循环
中断处理完成后操作系统会返回主循环并等待下一个中断;
-
信号的处理时机
当进程接收到一个信号时并不会立即处理这个信号,而是等待合适的时候对该信号进行处理;
信号的处理是由进程完成的,这意味着此时进程必须进入内核态才能对信号进行处理;
信号的检测与处理的时机为进程由内核态返回到用户态的过程;
进程在内核态时意味着其必定在进行重要的工作,只有当重要的工作完成时即从内核态返回用户态的时机才有机会对信号进行检测;
该图为以基于用户自定义动作处理信号为例;
处理这个信号,而是等待合适的时候对该信号进行处理;
信号的处理是由进程完成的,这意味着此时进程必须进入内核态才能对信号进行处理;
信号的检测与处理的时机为进程由内核态返回到用户态的过程;
进程在内核态时意味着其必定在进行重要的工作,只有当重要的工作完成时即从内核态返回用户态的时机才有机会对信号进行检测;