【嵌入式八股12】RTOS
一、内核态与用户态的区别
- 本质区别:内核态和用户态主要区别在于运行级别以及对硬件的操作权限。用户态下,程序受到诸多限制,不能直接操作硬件;而内核态具有更高的权限,可以对系统的硬件资源进行直接访问和控制。
- 状态切换方式:从用户态切换到内核态通常有三种方式:系统调用、异常和外围设备中断。系统调用是用户程序主动向操作系统内核请求服务的一种方式;异常是指程序运行过程中出现的错误或特殊情况,如除零错误等,会触发系统进入内核态进行处理;外围设备中断则是由外部设备(如键盘、鼠标等)发出的中断信号,使系统从用户态切换到内核态来处理设备的请求。
二、进程与线程
- 概述区别
- 地址空间:进程是资源分配的最小单位,拥有独立分配的内存空间,包括代码段、数据段、堆栈段等。线程是 CPU 调度的最小单位,线程共享其所属进程的内存空间。真正在 CPU 上运行的是线程,多个线程可以在同一进程的地址空间内并发执行。
- 开销差异:进程切换开销较大,因为切换时需要保存和恢复整个进程的上下文环境,包括内存空间、寄存器状态等。而线程是轻量级的,切换时只需保存和恢复少量的线程上下文信息,开销相对较小。
- 并发性表现:进程的并发性相对较差,由于每个进程都有独立的地址空间,进程间的通信和同步较为复杂。而线程在同一进程内可以更方便地并发执行,共享进程的资源,提高了系统的并发性能。
- 崩溃影响:线程的崩溃不一定导致进程的崩溃,因为线程共享进程的资源,某个线程的异常可能不会影响到其他线程的正常运行。但如果一个线程出现严重错误,如访问非法内存等,可能会导致整个进程崩溃。线程在进程的环境下运行,就像车厢依赖于火车才能运行一样。一个进程可以包含多个线程,如同一辆火车可以有多个车厢。不同进程间的数据很难共享,因为它们有独立的地址空间,就像不同火车上的乘客很难换到另一辆火车上(比如站点换乘);而同一进程下不同线程间数据很容易共享,例如从 A 车厢换到 B 车厢很容易。进程要比线程消耗更多的计算机资源,因为进程拥有独立的资源,就像采用多列火车相比多个车厢更耗资源。进程间不会相互影响,一个进程的崩溃不会影响到其他进程,就像一列火车不会影响另一列火车;但如果一个进程中的一个线程挂掉,可能会导致整个进程挂掉,比如一列火车上中间的一节车厢着火了,将影响到所有车厢。进程可以拓展到多机环境,即不同的进程可以在不同的计算机上运行,就像不同火车可以开在多个轨道上;而线程最多适合在多核环境下运行,同一进程的线程不能在行进的不同的轨道上(不同的 CPU 核心上独立运行,需要进程的调度和管理)。
- 资源占用:每个进程都有独立的内存空间,包括代码、数据、堆栈等,在创建、切换和销毁进程时,涉及到较大的资源开销。而线程共享所属进程的内存空间,线程切换和创建时的开销较小。
- 并发性:进程是独立运行的执行单位,多个进程之间可以并发执行,每个进程都有自己的执行状态、程序计数器和堆栈指针等。线程是进程内的执行流,多个线程共享进程的资源,在同一进程中的多个线程可以并发执行,提高了程序的执行效率。
- 通信和同步:进程间的通信比较复杂,需要通过特定的机制,如管道、消息队列、共享内存等进行数据的传递和共享。而线程之间共享进程的资源,通信相对容易,可以直接访问共享的内存变量。但在多线程编程中,线程之间需要通过同步机制,如锁、信号量、条件变量等,来保证数据的一致性和正确性,避免出现竞争条件。
- 安全性:由于线程共享进程的资源,多个线程之间对共享数据的访问需要进行同步控制,否则可能会出现竞争条件(Race Condition)和数据不一致的问题。相比之下,进程间的数据相对独立,每个进程拥有独立的内存空间,因此进程在安全性方面更有优势。
- 何时使用进程与线程
- 多进程:
- 优点:进程独立,一个进程的崩溃不会影响主程序的稳定性,并且可以充分利用多 CPU 进行并行计算,提高系统的性能。
- 缺点:逻辑相对复杂,进程间的 IPC(Inter-Process Communication,进程间通信)比较困难,需要使用专门的通信机制;调度开销大,创建、切换和销毁进程都需要消耗较多的系统资源。
- 多线程:
- 优点:线程间通信方便,因为它们共享进程的内存空间,可以直接访问共享变量;资源开销小,线程的创建、切换和销毁相对进程来说更加高效;程序逻辑相对简单,适用于一些对并发要求较高但数据共享较为频繁的场景。
- 缺点:线程间实现独立互斥比较困难,需要使用同步机制来保证数据的一致性;线程崩溃可能会影响到整个进程,因为线程共享进程的资源,一个线程的异常可能会导致进程出现问题。
- 选择建议:对于频繁创建和销毁的任务,使用线程更为合适,因为线程的开销较小;对于 CPU 密集型的任务,使用进程可以充分利用多核 CPU 的性能,提高计算效率;对于 I/O 密集型的任务,使用线程可以在等待 I/O 操作完成的时间内,让其他线程继续执行,提高系统的并发性能。总结来说,若追求安全稳定,优先选择进程;若需要快速频繁地进行任务切换和数据共享,选择线程更为合适。
- 多进程:
三、进程切换比线程切换慢的原因
- 上下文保存差异:进程切换涉及到页表的切换,页表用于将虚拟地址映射到物理地址。当页表切换时,实质上会导致 TLB(Translation Lookaside Buffer,转换后援缓冲器)的缓存全部失效,因为 TLB 中存储的是最近使用的页表项。此时,这些寄存器里的内容需要全部重写,以更新为新进程的页表信息,这一过程会消耗较多的时间。而线程切换无需经历页表的切换,因为线程共享进程的地址空间,所以线程切换的开销相对较小。
- 线程栈相关:线程切换主要涉及到线程栈的切换,保存和恢复线程的局部变量、函数调用栈等信息。虽然线程栈的切换也需要一定的时间,但相比进程切换时大量的上下文信息(包括内存空间、页表等)的保存和恢复,线程切换的开销要小得多。
四、进程可以创建线程的数量
进程可以创建的线程数量由可用虚拟空间和线程的栈的大小共同决定。在一个典型的系统中,一个进程可用虚拟空间通常是 2G。默认情况下,线程的栈的大小是 1MB。因此,理论上最多只能创建 2048 个线程(2G / 1MB = 2048)。但在实际应用中,由于系统还需要为其他资
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
嵌入式八股/模拟面试拷打 文章被收录于专栏
一些八股模拟拷打Point,万一有点用呢