网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
- 混合内核 : 架构和微内核类似,实现是宏内核.
- windows NT 内核 NT:new technology
- 也支持Multitask 和 SMP(对称多处理) , 混合类型的内核,
- 有自己的可执行文件格式 PE 。
内核态与用户态
Kernel 运行在超级权限模式(Supervisor Mode)下,所以拥有很高的权限。按照权限管理的原则,多 数应用程序应该运行在最小权限下。
操作系统将内存分成了两个区域:
- 内核空间(Kernal Space),这个空间只有内核程序可以访问.
- 用户空间(User Space),这部分内存专门给应用程序使用。
- 内核态:在内核态空间运行的程序 用户态 : 在用户空间运行的程序。
系统调用过程
- 内核程序执行在内核态(
Kernal Mode
),用户程序执行在用户态(User Mode
)。当发 生系统调用时,用户态的程序发起系统调用。因为系统调用中牵扯特权指令,用户态程序权限不足,因 此会中断执行,也就是Trap
(Trap 是一种中断)。
进程与线程
- 一个应用程序启动后会在内存中创建一个执行副本,这就是进程。
Linux
的内核是一个Monolithic Kernel
(宏内核),因此可以看作一个进程。也就是开机的时候,磁盘的内核镜像被导入内存作为一个 执行副本,成为内核进程。 - 进程可以分成用户态进程和内核态进程两类。用户态进程通常是应用程序的副本,内核态进程就是内核 本身的进程。如果用户态进程需要申请资源,比如内存,可以通过系统调用向内核申请。
- 程序在现代操作系统中并不是以进程为单位在执行,而是以一种轻量级进程(Light Weighted Process),也称作线程(Thread)的形式执行。
- 一个进程可以拥有多个线程。进程创建的时候,一般会有一个主线程随着进程创建而创建。
那么用户态进程如果要执行程序,是否也要向内核申请呢?
其实不是,进程可以通过 API 创建用户态的线程,也可以通过系统调用创建内核态的线程。
用户态线程
- 用户态线程也称作用户级线程(User Level Thread),完全是在用户空间中创建
优点 - 管理开销小:创建、销毁不需要系统调用。
- 切换成本低:用户空间程序可以自己维护,不需要走操作系统调度。
缺点 - 与内核协作成本高:比如这种线程完全是用户空间程序在管理,当它进行 I/O 的时候,无法利用到 内核的优势,需要频繁进行用户态到内核态的切换。
- 线程间协作成本高:设想两个线程需要通信,通信需要 I/O,I/O 需要系统调用,因此用户态线程 需要支付额外的系统调用成本。
- 无法利用多核优势:比如操作系统调度的仍然是这个线程所属的进程,所以无论每次一个进程有多 少用户态的线程,都只能并发执行一个线程,因此一个进程的多个线程无法利用多核的优势。
- 操作系统无法针对线程调度进行优化:当一个进程的一个用户态线程阻塞(Block)了,操作系统 无法及时发现和处理阻塞问题,它不会更换执行其他线程,从而造成资源浪费。
内核态进程
- 内核态线程也称作内核级线程(Kernel Level Thread)。这种线程执行在内核态,可以通过系统调用创 造一个内核级线程。
优点 - 可以利用多核 CPU 优势:内核拥有较高权限,因此可以在多个 CPU 核心上执行内核线程。
- 操作系统级优化:内核中的线程操作 I/O 不需要进行系统调用;一个内核线程阻塞了,可以立即让 另一个执行。
缺点 - 创建成本高:创建的时候需要系统调用,也就是切换到内核态。
- 扩展性差:由一个内核程序管理,不可能数量太多。
- 切换成本较高:切换的时候,也同样存在需要内核操作,需要切换内核态。
用户态线程和内核态线程之间的映射关系
- 线程简单理解,就是要执行一段程序。程序不会自发的执行,需要操作系统进行调度。
如果有一个用户态的进程,它下面有多个线程。如果这个进程想要执行下面的某一个线程,应 该如何做呢?
将需要执行的程序,让一个内核线程去执行,内核线程是真正的线程。因为它会分配到 CPU 的执行资源。用户态线程创建成本低,问题明显,不可以利用多核。内核态线程,创建成本高,可以利用 多核,切换速度慢。因此通常我们会在内核中预先创建一些线程,并反复利用这些线程。
多对一(Many to One)
- 用户态进程中的多线程复用一个内核态线程。这样,极大地减少了创建内核态线程的成本,但是线程不 可以并发。
一对一(One to One)
- 该模型为每个用户态的线程分配一个单独的内核态线程,在这种情况下,每个用户态都需要通过系统调 用创建一个绑定的内核线程,并附加在上面执行.
- 因为线程较多,对内核调度的压力会明显增加。
多对多(Many To Many)
- n 个用户态线程分配 m 个内核态线程。m 通常可以小于 n,一种可行的策略是将 m 设 置为核数,减少了内核线程,同时也保证了多核心并发。
两层设计(Two Level)
- 混合了多对多和一对一的特点
中断和中断向量
中断的设计
- 第一层是硬件设计、第二层是操作系统设计、第三层是程序语言的设计。
- 按键码的收集,是键盘芯片和主板的能力。主板知道有新的按键后,通知 CPU,CPU 要中断当前执行的 程序,将 PC 指针跳转到一个固定的位置,我们称为一次中断(interrupt)。
- 中断类: 中断识别码。
- 中断向量(Interupt Vector) : PC指针跳转的地址,存储zai中断向量表中。
- PU 接收到中断后,CPU 根据中断类型操作 PC 指针,找到中断向量。操作系统必须在这之前,修 改中断向量,插入一条指令。比如操作系统在这里写一条Jump指令,将 PC 指针再次跳转到自己处理对 应中断类型的程序。
- 作系统接管之后,以按键程序为例,操作系统会进行一些处理,包括下面的几件事情:
- 1.将按键放入一个队列,保存下来。这是因为,操作系统不能保证及时处理所有的按键,比如当按键 过快时,需要先存储下来,再分时慢慢处理。
- 2.计算组合键。可以利用按下、释放之间的时间关系。
-
- 经过一定计算将按键抽象成消息(事件结构或对象)。
-
- 提供 API 给应用程序,让应用程序可以监听操作系统处理后的消息。
-
- 分发按键消息给监听按键的程序。
中断的类型
1、 触发方分成同步中断和异步中断;
2、是否强制触发分成可屏蔽中断和不可屏蔽中断。
- 中断可以由 CPU 指令直接触发,这种主动触发的中断,叫作同步中断。
- 系统调用,需要从用户态切换内核态,这种情况需要程序触发一个中断,叫作陷阱 (Trap),中断触发后需要继续执行系统调用。
- 错误(Fault),通常是因为检测到某种错误,需要触发一个中断,中断响 应结束后,会重新执行触发错误的地方,比如后面我们要学习的缺页中断。
- 最后还有一种情况是程序的异常,这种情况和 Trap 类似,用于实现程序抛出的异常
- 另一部分中断不是由 CPU 直接触发,是因为需要响应外部的通知,比如响应键盘、鼠标等设备而触发的 中断。这种中断我们称为异步中断。
- CPU 通常都支持设置一个中断屏蔽位(一个寄存器),设置为 1 之后 CPU 暂时就不再响应中断。对于 键盘鼠标输入,比如陷阱、错误、异常等情况,会被临时屏蔽。但是对于一些特别重要的中断,比如 CPU 故障导致的掉电中断,还是会正常触发。可以被屏蔽的中断我们称为可屏蔽中断,多数中断都是可 屏蔽中断。
思考题
Linux 内核和 Windows 内核有什么 区别?
- Windows 有两个内核,最新的是 NT 内核,目前主流的 Windows 产品都是 NT 内核。NT 内 核和 Linux 内核非常相似,没有太大的结构化差异。
- 从整体设计上来看,Linux 是宏内核,NT 内核属于混合型内核。和微内核不同,宏内核和混合类型内核 从实现上来看是一个完整的程序。只不过混合类型内核内部也抽象出了微内核的概念,从内核内部看混 合型内核的架构更像微内核。
- 其他差异 : Linux 内核是一个开源的内核;它们支持的可执行文件格式不同;它们用到的虚拟化技术不同
Unix 和 Macintosh 内核属于哪种类型?
- Unix : 宏内核。
- Mac OS 用的是 XNU 内核, XNU 是一种混合型内核,XNU 是 X is not Unix 的意思, 是一个受 Unix 影响很大的内核。
用户态线程和内核态线程的区别?
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新