嵌入式 操作系统(四)
更多专栏:
超详细的嵌入式面经专栏(适用于小白学习和大佬复习):https://www.nowcoder.com/creation/manager/columnDetail/mGYoDz
校招公司汇总专栏:https://www.nowcoder.com/creation/manager/columnDetail/0ybKdp
目录:
1.线程池设计思路
2.请你说说什么是孤儿进程、僵尸进程、守护进程?
3.什么是并发,同步,异步,互斥,阻塞,非阻塞?
4.你了解死锁吗?请你说说产生的条件?如何解决?
5.什么是互斥锁机制?互斥锁和读写锁有什么区别?
6.什么是自旋锁,和互斥锁有什么区别?
内容:
1.线程池设计思路
设计线程池的原因
- 减少线程创建和销毁的开销
- 控制线程数量,避免资源浪费
- 线程池中的线程是预先创建好的,任务一到达,线程池就能立刻分配线程来执行任务,极大地提高了任务响应的速度。
- 线程池可以设置任务的优先级,优先执行高优先级的任务,适用于任务有不同重要性的场景。
- 线程池的管理机制有助于避免线程泄漏。没有线程池时,线程的创建和销毁通常是由程序员手动管理的,容易出现线程未关闭或无法结束的情况,导致线程泄漏,占用系统资源。
如何设计一个线程池
- 创建一个线程安全的任务队列,充当生产者消费者队列,作为临界资源。
- 初始化n个线程,并让它们进入等待状态,准备处理任务。
- 当任务队列为空时,所有线程阻塞,等待新任务的到来。
- 当生产者队列来一个任务之后,先对队列进行加锁,然后把任务挂到队列上。使用条件变量通知一个阻塞中的线程来处理任务。
线程池中线程数量
注意:线程池中线程数量与CPU核数、IO、并行、并发有关。
- CPU密集型任务:对于 CPU 密集型任务,建议将线程池大小设置为CPU核心数量+1,因为 CPU 密集型任务不会并行执行得更快,反而会受到线程切换和上下文切换的影响。这样可以保持CPU的高利用率。
- I/O密集型任务:对于 I/O 密集型任务,线程池的大小可以设置得更大,因为这些任务通常会在等待 I/O 操作时阻塞,因此可以通过增加线程数来更好地利用系统资源。,建议将线程池大小设置为2*CPU核心数量+1。
- 并行度和响应性需求:线程池的大小还受到任务的并行度和对响应性的需求影响。最佳线程数目 = (线程等待时间/线程CPU时间 + 1)* CPU数目。
2.请你说说什么是孤儿进程、僵尸进程、守护进程?
孤儿进程
孤儿进程是指一个子进程的父进程在子进程还未结束时已经终止了。这意味着子进程的父进程消失了,而该子进程仍然在运行。
为什么会出现孤儿进程
- 当一个进程创建了子进程(即父进程是子进程的父进程),如果父进程提前终止(无论是正常退出还是崩溃),子进程就会成为孤儿进程。
- 操作系统为了避免孤儿进程影响系统稳定性,通常会将这些孤儿进程的父进程设置为 init进程(在 UNIX/Linux 系统中是进程号为1的进程)。init进程将会收养这些孤儿进程,成为它们的父进程,并负责清理资源。
例子:
假设进程 A 创建了进程 B。如果进程 A 退出,而进程 B 还在运行,那么进程 B 就变成了孤儿进程。此时,init进程会成为进程 B 的父进程。
僵尸进程
僵尸进程是指已经完成执行的进程,但其父进程还没有调用 wait()
或 waitpid()
来回收该进程的资源,因此它仍然保留在进程表中。
为什么会出现僵尸进程
- 当一个进程完成执行后,操作系统会保留该进程的部分信息(如进程ID、退出状态等)以供父进程获取。如果父进程没有及时调用
wait()
来获取子进程的退出状态,子进程的资源就无法被释放。 - 虽然僵尸进程的执行已完成,但它依然占据操作系统的进程表项。
检查和清理僵尸进程
使用 ps
或 top
查找僵尸进程
- 使用命令
ps aux | grep 'Z'
来查找系统中所有的僵尸进程。Z
表示该进程是僵尸进程。
ps aux | grep 'Z'
- 使用
top
命令检查僵尸进程。在top
中,僵尸进程通常显示为Z
状态。
杀死父进程
如果父进程没有回收子进程的资源,可以通过终止父进程来让 init
进程收养子进程,然后由 init
进程回收资源。
- 查找父进程的PID:使用
ps -ef
查找僵尸进程的父进程 ID(PID)。 - 杀死父进程:使用
kill
命令终止父进程。
kill -9 <parent_pid>
一旦父进程被终止,init
进程会收养子进程并回收它们,僵尸进程就会被清除。
例子:
假设进程 A 创建了进程 B。进程 B 执行完成,但父进程 A 没有调用 wait()
。此时,进程 B 就变成了僵尸进程。直到进程 A 调用 wait()
或退出后,init
进程回收 B,僵尸进程才会消失。
守护进程
守护进程是在后台运行不受终端控制的进程(如输入、输出等)。网络服务大部分就是守护进程。
为什么需要守护进程
- 守护进程通常在系统启动时启动,且一直运行,直到系统关闭。它们提供了服务,通常是系统的核心功能服务,如网络服务、日志管理、系统监控等。
- 守护进程通常不需要用户交互,而是自动化地执行某些任务。
守护进程的创建过程:
- 创建子进程:一个进程调用 fork() 来创建子进程。
- 子进程脱离终端:子进程通过调用 setsid() 来创建一个新的会话,并使自己成为会话的领导者,脱离终端。
- 关闭文件描述符:守护进程会关闭从父进程继承的文件描述符,避免它们与终端、标准输入/输出产生关联。
- 在后台运行:守护进程开始执行其后台任务,并将自己的输出定向到日志文件等地方。
例子:
sshd
:在 Linux 系统中,sshd
(SSH 守护进程)负责处理远程登录连接。它会在系统启动时启动,并保持在后台运行,等待用户通过 SSH 协议连接。cron
:cron
守护进程定期执行系统任务(如定时备份、清理日志等)。
3.什么是并发,同步,异步,互斥,阻塞,非阻塞?
并发
并发指的是在同一时间段内处理多个任务的能力。并发并不意味着这些任务一定是在同一时刻同时执行,而是指在一个时间段内可以对多个任务进行调
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
本人双飞本,校招上岸广和通。此专栏覆盖嵌入式常见面试题,有C/C++相关的知识,数据结构和算法也有嵌入式相关的知识,如操作系统、网络协议、硬件知识。本人也是校招过来的,大家底子甚至项目,可能都不错,但是在面试准备中常见八股可能准备不全。此专栏很适合新手学习基础也适合大佬备战复习,比较全面。最终希望各位友友们早日拿到心仪offer。也希望大家点点赞,收藏,送送小花。这是对我的肯定和鼓励。 持续更新