“内核”指的是一个提供硬件抽象层、磁盘及文件系统控制、多任务等功能的系统软件。内核是操作系统最基本的部分。它是为众多应用程序提供对计算机硬件的安全访问的一部分软件,这种访问是有限的,并且内核决定一个程序在什么时候对某部分硬件操作多长时间。直接对硬件操作是非常复杂的,所以内核通常提供一种硬件抽象的方法来完成这些操作。硬件抽象隐藏了复杂性,为应用软件和硬件提供了一套简洁,统一的接口,使程序设计更为简单。
简单明了用一张图概括:
操作系统内核(Kernal)是一组应用软件,这个软件能够控制所有硬件及计算机活动。如硬盘访问、网卡传输和键盘开始工作等,开机后内核程序将会常驻受保护的内存中。硬件由内核管理后,操作系统将会提供一组系统调用接口,帮助完成诸如显示、读写设备等基本操作,架构是计算机硬件的组织形式,架构不同则内核也不同(Arm架构和x86架构)。操作系统在计算机结构中的位置如下:
红色部分则是操作系统。在编程程序的时候,我们将会使用当前系统的系统调用来辅助完成编写,这意味着程序时与系统绑定的,如果你更换了系统,程序自然也就失效了(这就是为什么Windows可执行程序和Linux程序不互通的原因:依赖的系统API不通用)
内核功能至少包含以下几部分:
- 系统调用接口(System call interface)
- 程序管理(Process control)
- 内存管理(Memory management)
- 文件系统管理(FileSystem management)
- 设备驱动(Device driver)
硬件驱动的提供者应该是硬件厂商的事情,用户只需要根据给定的驱动程序进行编程即可。
操作系统内核是你永远看不到的。它基本上允许任何其他程序执行。它处理硬件事件(称为中断)、软件事件(称为系统调用)和管理资源的访问。
硬件事件处理(中断)会获取到你刚才按下的键,并将按键转化为对应的字符并存在缓冲区中,某些程序就可以在缓冲区里检索到该字符并判断出你按下的是哪个键。
软件事件处理(系统调用)是由用户级的程序触发的,像打开文件,启动程序等。每一次的系统调用都需要判断传递的参数是否有效,然后执行内部操作完成处理。
大多数的用户程序是不会直接发出系统调用的(个别除外,比如ASM),而是使用标准库,标准库可以格式化内核需要的参数并产生一个系统调用(如:C语言中的函数fopen()最终是调用了内核函数,这才能打开文件)。
内核为了保存最后操作的状态通常定义了一些抽象的文件、进程、套接字、目录等,这也使得内核保存最后状态变的更高效容易。
1.宏内核
内核的功能都集中在一起,运行在内核进程中,模块之间的交互直接通过方法调用
2.微内核
微内核中,内核只提供最核心的功能,如任务调度、内存管理,其他模块都被移除内核,运行在不同进程,这样即使某一个模块出现问题,只要重启该进程即可;但是该种做法需要使用IPC作为进程间通信的方式,进程间的效率较低
3.混合内核
宏内核和微内核的结合体,混合内核就是集中了两者的特点,让微内核的一些核心模块运行在内核中,从而使得内核效率更高
4.外内核
外内核就是把硬件暴露给应用程序,应用程序可以直接访问硬件,外内核对系统提供保护
宏内核 | 微内核 | |
---|---|---|
通信效率 | 高(函数调用) | 低(进程间通信) |
稳定性 | 低(模块集成在一起) | 高(模块间互不影响) |
扩展性 | 低(模块集成在一起) | 高(模块间互不影响) |
代码量 | 多(需要实现所有模块) | 少(只需要实现核心功能) |
宏内核
Linux
Windows 9X 系列
MacOS 8.6 版本之前
微内核
Fuchsia
鸿蒙
Minix
混合内核
Windows XP
Windows 7
Mac OS X
XNU
外内核 Nemesis
内存分区
- 内核空间:只有内核程序可以访问
- 用户空间:专门给应用程序使用后
⽤户空间的代码只能访问⼀个局部的内存空间,而内核空间的代码可以访问所有内存空间。因此,当程序使用用户空间时,我们常说该程序在用户态执行,而当程序使内核空间时,程序则在内核态执行。
应用程序如果需要进⼊内核空间,就需要通过系统调用。
当应用程序使用系统调用时,会产生一个中断。发生中断后, CPU 会中断当前在执行的用户程序,转而跳转到中断处理程序,也就是开始执行内核程序。内核处理完后,主动触发中断,把CPU执行权限交回给用户程序,回到⽤户态继续⼯作
内核态:也叫内核空间,是内核进程/线程所在的区域。主要负责运行系统、硬件交互。运行的代码不受任何限制,CPU可以执行任何指令
用户态:也叫用户空间,是用户进程/线程所在的区域。主要用于执行用户程序。运行的代码需要受到CPU的很多检查,不能直接访问内核数据和程序,也就是说不可以像内核态线程一样访问任何有效地址。
操作系统在执行用户程序时,主要工作在用户态,只有在其执行没有权限完成的任务时才会切换到内核态。为什么要区分内核态和用户态?保护机制。防止用户进程误操作或者是恶意破坏系统。内核态类似于C++的私有成员,只能在类内访问,用户态类似于公有成员,可以随意访问。
用户态切换到内核态的方式
由于用户态无法完成某些任务,用户态会请求切换到内核态,内核态通过为用户专门开放的中断完成切换。(打开文件,键盘事件监听)
在执行用户程序时出现某些不可知的异常,会从用户程序切换到内核中处理该异常的程序,也就是切换到了内核态。
外围设备发出中断信号,当中断发生后,当前运行的进程暂停运行,并由操作系统内核对中断进程处理,如果中断之前CPU执行的是用户态程序,就相当于从用户态向内核态的切换。
多任务(MutiTask)
代表Linux是一个多任务的操作系统
1. 对于单核CPU时,可以让任务执行一小段时间,时间一到就切换到另一个任务。从宏观角度来说,一段时间执行了多个任务,这被称为并发。
2. 对于多核CPU时,多个任务可以同时被不同的核心的CPU同时执行,这被称为并行。
对称多处理(SMP)
代表着每个 CPU 的地位是相等的,对资源的使用权限也是相同的,多个 CPU 共享同⼀个内存,每个 CPU 都可以访问完整的内存和硬件资源。 这个特点决定了 Linux 操作系统不会有某个 CPU 单独服务应用程序或内核程序,而是每个程序都可以被分配到任意⼀个 CPU 上被执行,
可执行文件链接格式(ELF)
它是Linux操作系统中可执行文件的存储格式。
宏内核(Monolithic Kernel)
Linux 内核架构就是宏内核,意味着 Linux 的内核是⼀个完整的可执行程序,且拥有最高的权限。
宏内核的特征是系统内核的所有模块,比如进程调度、内存管理、⽂件系统、设备驱动等,都运行在内核态。
Linux 也实现了动态加载内核模块的功能,例如⼤部分设备驱动是以可加载模块的形式存在的,与内 核其他模块解藕,让驱动开发和驱动加载更为方便、灵活。
Windows 和 Linux ⼀样,同样⽀持 MutiTask 和 SMP,但不同的是,Window 的内核设计是混合型内核,Windows 的可执行文件的格式与 Linux 也不同,所以这两个系统的可执行文件是不可以在对方上运行的。 Windows 的可执行文件格式叫 PE,称为可移植执行⽂件,扩展名通常是 .exe 、.dll 、 .sys 等。