操作系统(一)系统结构
存储结构
为什么计算机要给储存结构分级?
不同级别的储存结构具有不同的访问速度,CPU 访问 CPU Cache 的延时只需要几个时钟周期,访问物理内存的延时则是几百个,速度相差 100 倍,访问磁盘延时就更高了,已经到毫秒级别了(百万时钟周期),但是访问速度越快的存储器,造价成本会高很多,容量也比较小。 通过分级储存结构,可以将数据按照不同的访问速度、容量和成本要求进行管理,CPU Cache用于存储近期频繁访问的数据,内存用于存储当前执行的程序和数据,而硬盘则用于存储大量数据和长期存储。(一个时钟周期小于10纳秒)
CPU cache L1 L2 L3 读取数据的时间量级差距有多大?
CPU 访问 L1 Cache 只需要 2~4 个时钟周期,访问 L2 Cache 大约 10~20 个时钟周期,访问 L3 Cache 大约 20~60 个时钟周期,而访问内存速度大概在 200~300 个 时钟周期之间。
CPU 缓存对程序性能的影响都体现在哪些方面?
程序具有局部性原理:如果一个数据被访问,那么附近的数据很可能也会被访问到,
CPU Cache就是基于这个局部性原理,在访问数据的时候,如果访问的数据不在 CPU Cache中,不会只从内存读这一个数据,而是会从内存连续加载数据到 CPU Cache,这样相邻的数据都会被缓存在 CPU Cache,那么程序在访问相邻数据的时候,相邻数据就可以直接在缓存中命中,无需访问内存,可以提高访问的效率。
内核态
什么是内核?
内核是系统中第一个加载的程序,并拥有最高的特权级别,控制整个系统的运行和资源分配。
负责管理进程、线程:决定哪个进程、线程使用 CPU,也就是进程调度的能力;
管理内存:决定内存的分配和回收,也就是内存管理的能力;
管理硬件设备:为进程与硬件设备之间提供通信能力;
提供系统调用:它与用户空间程序进行交互,提供系统调用接口,实现了操作系统的基本功能。
内核态和用户态区别?为什么要区分内核态和用户态?
CPU 将指令分为了特权指令和非特权指令,然后操作系统根据 CPU 的特权分级机制,把进程的运行空间分为内核空间和用户空间。
内核态具有最高权限,可以执行特权指令,直接访问所有系统和硬件资源,而用户态不能执行特权指令,只能执行非特权指令,所以只能访问受限的资源,比如不可以直接访问内存、硬盘、网卡等硬件设备,如果要访问这些硬件资源,需要通过系统调用的方式,让进程陷入到内核态才能访问这些特权资源。
之所以要区分内核态和用户态,目的就是为了保证系统的稳定性和安全性,因为通过限制应用程序对特权指令的访问,可以防止恶意程序直接操作危险的指令导致系统崩溃的问题。
什么时候会由用户态陷入内核态?
主要有三种情况,会导致应用程序从用户态陷入到内核态:
应用程序执行系统调用的时候,会触发一个软中断,会进入内核态执行相应的内核代码,完成后再返回用户态。
当应用程序发生异常情况,如访问非法内存、除零错误等,CPU会触发一个异常,将控制权转移到内核态的异常处理程序中。
当系统接收到外部设备的中断信号,如硬件设备的输入/输出请求、定时器中断等,处理器会中断当前的执行,进入内核态执行相应的中断处理程序。
第一种属于软件中断,后两种属于硬件中断
系统调用的过程?
当应用程序发生系统调用的时候,会发生用户态和内核态的切换,过程是这样的:
- 执行系统调用的时候,先将系统调用名称转换为系统调用号,接着将系统调用号和请求的参数放到寄存器中,然后执行软件中断命令,CPU会从用户态切换到内核态。
- CPU 跳转到中断处理程序,将当前用户态的现场信息保存到内核栈中,接着根据系统调用号从系统调用表中找到对应的系统调用函数,并将寄存器中保存的参数取出来,作为函数参数,然后在内核中执行系统调用函数。
- 执行完系统调用后,执行中断返回指令,内核栈会弹出之前保存的用户态的现场信息,将原来用户态保存的现场恢复回来,这时候 CPU 恢复到用户态,用户态进程恢复执行。
用户态和内核态是如何切换的?
简单就参考系统调用的过程?
为什么用户态和内核态的相互切换过程开销比较大
- 上下文切换:在用户态和内核态之间切换时,需要保存当前进程或线程的上下文信息,包括程序计数器、寄存器状态、栈指针等。这些上下文信息保存在内存中或者内核数据结构中,在切换完成后需要再次加载回来。这个过程会消耗一定的时间和资源。
- 权限切换:用户态和内核态具有不同的权限级别,内核态拥有更高的特权级别,可以执行一些用户态不可访问的指令和操作。因此,从用户态切换到内核态需要进行特权级别的变更,这个过程也会增加开销。
- 地址空间切换:用户态和内核态通常有不同的地址空间,为了保护操作系统内核不受用户程序的直接影响,当切换到内核态时需要进行地址空间的切换和映射,这也会增加开销。
- TLB刷新:TLB是CPU中的一种缓存,用于存储虚拟地址到物理地址的映射关系。当发生用户态和内核态的切换时,可能导致TLB中的缓存无效,需要进行TLB刷新,这会引起一定的性能损失。
中断
什么是中断?为什么要有中断?
中断是系统用来响应硬件设备请求的一种机制,操作系统收到硬件的中断请求,会打断正在执行的进程,然后调用内核中的中断处理程序来响应请求。
中断机制的好处是化主动为被动,避免 CPU 轮询等待某条件成立。如果没有中断机制,那么“某个条件成立”就需要 CPU 轮询判断,这样就会增加系统的开销。而使用中断机制,就可以在条件成立之后,向 CPU 发送中断事件,强制中断 CPU 执行程序,转而去执行中断处理程序。
可以理解为中断是一种异步的事件处理机制,可以提高系统的并发处理能力。
什么是硬件中断和软件中断?
- 中断(interrupt):由硬件设备触发,比如点击一下鼠标、敲一下键盘,这时候外部设备会给 CPU 发送一个中断号,属于异步事件;
- 异常(exception):CPU 在执行指令时检测到的反常条件,比如除法异常、错误指令异常,缺页异常等,然后CPU 自己给自己一个中断号,无需外界给,属于同步事件;
- INT 指令:INT 指令后面跟一个数字,就相当于直接用指令的形式,告诉 CPU 一个中断号。比如 INT 0x80,就是告诉 CPU 中断号是 0x80。Linux 内核提供的系统调用,就是用了 INT 0x80 这种指令。
硬件中断:由硬件自动触发的中断就属于硬件中断,比如中断和异常都属于硬件中断,中断是由外部设备触发的,异常是由 CPU 触发的。
软件中断:由软件程序主动触发的中断属于软件中断,比如 INT 指令,Linux 内核提供的系统调用,就是用了 INT 0x80 这种指令。
什么是硬中断和软中断?
根据实现的方式的不同,分为了硬中断和软中断:
- 由 CPU 硬件实现的中断机制,就属于硬中断,比如中断、异常、INT指令都是由 CPU 实现的中断机制。 ( CPU 在每一个指令周期的最后,都会留一个 CPU 周期去查看是否有中断,如果有,就把中断号取出,去「中断向量表」中寻找中断处理程序,然后跳过去执行中断处理程序。)
- 由软件实现的中断机制,就属于软中断。比如 Linux 实现的软中断守护进程。 (一个单独的守护进程,不断轮询一组标志位,如果哪个标志位有值了,那去这个标志位对应的「软中断向量表数组」的相应位置,找到软中断处理函数,然后跳过去执行软中断处理函数。)
硬中断和软中断的中断效果是一样的,都是打断当前正在运行的程序,转而去执行中断处理程序,执行完之后再返回原程序。
为什么要有软中断?
软中断可以承接原本硬中断处理程序比较复杂且耗时的工作,让硬中断的中断处理函数的逻辑尽可能的简单,从而提高系统的中断响应速度。
比方说,在网卡收到数据包的时候,会把数据包的事件分为上半部分和下半部分:
- 上部分由硬中断处理程序处理,要做的事情很少,做完后就会发起了一次软中断,然后就结束了。这里发起的软中断,并不是向 CPU 发送中断信号,而是将软中断标记数组中的某一个位置标记一下。
- 下半部由软中断处理程序处理,内核守护进程会不断轮询软中断标记数组,看哪个位置被标记为 1 了,接着就去软中断向量表里,寻找这个标志位对应的处理程序,然后执行软中断处理程序处理,其主要是需要从内存中找到网络数据,再按照网络协议栈,对网络数据进行逐层解析和处理,最后把数据送给应用程序。