【秋招】嵌入式面试八股文 - 操作系统 篇
本文为 第六章操作系统 部分,具体整篇目录可以看前言!
第一部分(纯八股)
6. 操作系统
6.1 什么是进程?什么是线程?
进程是资源分配的基本单位,它是程序执行时的一个实例,在程序运行时创建。
线程是程序执行的最小单位,是进程的一个执行流,一个进程由多个线程组成的。
协程是一种比线程更加轻量级的存在。一个线程也可以拥有多个协程。其执行过程更类似于子例程,或者说不带返回值的函数调用。
6.2 内核线程和用户线程的区别?
1. 内核支持线程是OS内核可感知的,而用户级线程是OS内核不可感知的。
2. 用户级线程的创建、撤消和调度不需要OS内核的支持,是在语言(如Java)这一级处理的;而内核支持线程的创建、撤消和调度都需OS内核提供支持,而且与进程的创建、撤消和调度大体是相同的。
3. 用户级线程执行系统调用指令时将导致其所属进程被中断,而内核支持线程执行系统调用指令时,只导致该线程被中断。
4. 在只有用户级线程的系统内,CPU调度还是以进程为单位,处于运行状态的进程中的多个线程,由用户程序控制线程的轮换运行;在有内核支持线程的系统内,CPU调度则以线程为单位,由OS的线程调度程序负责线程的调度。
5. 用户级线程的程序实体是运行在用户态下的程序,而内核支持线程的程序实体则是可以运行在任何状态下的程序。
6.3 进程和线程有什么区别?
1、根本区别
进程是资源分配的基本单位,线程是程序执行的最小单位
2、资源开销
进程有自己独立地址空间(代码空间和数据空间),每启动一个进程,系统会为它分配地址空间。
线程没有自己独立的地址空间,线程共享进程中的数据,使用相同的地址空间。每个线程都有自己的堆栈。
线程切换的资源开销要比进程小。涉及频繁切换,就选择线程。
线程开销小,但是不利于进行资源包含;进程开销大,但是有利于资源保护。
3、关于通信
线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以通信的方式(IPC)进行。不过如何处理好同步与互斥是编写多线程程序的难点。(ftok函数)
但是多进程程序更健壮,多线程程序只要有一个线程死掉,整个进程也跟着死掉了,而一个进程死掉并不会对另外一个进程造成影响,因为进程有自己独立的地址空间。
4、执行过程
每个独立的进程有一个程序运行的入口、顺序执行序列和程序入口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
6.4 何时使用多进程,何时使用多线程?
对资源的管理和保护要求高,不限制开销和效率时,使用多进程。
要求效率高,频繁切换时,资源的保护管理要求不是很高时,使用多线程。
6.5 进程的几种状态?
关于IO:
用户程序进行IO的读写,会用到read&write两大系统调用。read系统调用,是把数据从内核缓冲区复制到进程缓冲区;而write系统调用,是把数据从进程缓冲区复制到内核缓冲区。
同步IO
是指用户空间线程是主动发起IO请求的一方,内核空间是被动接受方。
异步IO
是指内核kernel是主动发起IO请求的一方,用户线程是被动接受方。
6.6 进程创建的方式?
6.6.1 使用fork创建
创建新进程在Linux的下是由父进程来完成的,创建完成的新进程是子进程。
新进程的地址空间有两种可能性:
1、子进程是父进程的复制品(除了PID和task_struct是子进程自己的,其余的都从父进程复制而来
2、子进程装入另一个程序。
在Linux下的fork函数用于创建一个新的进程,使用fork函数来创建一个进程时,子进程只是完全复制父进程的资源。
6.6.2 fork和vfork的区别?
void exit( int status) 结束当前进程并将status返回;exit结束进程会刷新缓冲区
void _exit(int status) 这个不会进行缓冲区刷新
1. fork( )的子进程拷贝父进程的数据段和代码段;vfork( )的子进程与父进程共享数据段
2. fork( )的父子进程的执行次序不确定;vfork( )保证子进程先运行,在调用exec或exit之前与父进程数据是共享的,在它调用exec或exit之后父进程才可能被调度运行。
3. vfork( )保证子进程先运行,在它调用exec或exit之后父进程才可能被调度运行。如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。
4. 当需要改变共享数据段中变量的值,则拷贝父进程。
6.7 进程间通信方式有哪些?有什么优缺点?
6.7.1 管道(pipe)
管道这种通讯方式有两种限制:
一是半双工的通信,数据只能单向流动;
二是只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
缺点:速度慢,容量有限,只有父子进程能通讯。
6.7.2 流管道 s_pipe
可以进行双向传输(全双工);允许具有亲缘关系进程间通信;也允许无亲缘关系进程间通信。
6.7.3 信号量
信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
缺点:只能用来同步,不能用来进行传递复杂信息。
6.7.4 消息队列
容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题,消息队列可以不再局限于父子进程,而允许任意进程通过共享消息队列来实现进程间通信,并由系统调用函数来实现消息 发送和接收之间的同步,从而使得用户在使用消息缓冲进行通信时不再需要考虑同步问题,使用方便, 但是信息的复制需要额外消耗CPU的时间,不适宜于信息量大或操作频繁的场合。此种方法不太常用。
6.7.5 共享内存
利用内存缓冲区直接交换信息,无须复制,快捷、信息量大是其优点。共享内存块提供了在任意数量的 进程之间进行高效双向通信的机制。每个使用者都可以读取写入数据,但是所有程序之间必须达成并遵 守一定的协议,以防止诸如在读取信息之前覆写内存空间等竞争状态的出现。
6.8 线程创建方式
6.9 僵尸进程、孤儿进程、守护进程是什么?
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。
孤儿进程:父进程异常结束,子进程被进程Init所收养。
守护进程:创建守护进程时,有意把父进程结束,然后被1号进程init收养
区分:一个正常运行的子进程,如果此刻子进程退出,父进程没有及时调用wait或waitpid收回子进程的系统资源,该进程就是僵尸进程,如果系统收回了,就是正常退出,如果一个正常运行的子进程,父进程退出了但是子进程还在,该进程此刻是孤儿进程,被init收养,如果父进程是故意被杀掉,子进程做相应处理后就是守护进程
6.10 僵尸进程的危害?
在进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存等。但是仍然为其保留一定的信息(包括进程号PID,退出状态,运行时间等)。直到父进程通过wait / waitpid 来取时才释放。 如果进程不调用 wait / waitpid 的话, 那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程。
6.11 如何清理僵尸进程?
当系统中出现了僵尸进程时,我们是无法通过 kill 命令把它清除掉的。但是我们可以杀死它的父进程, 让它变成孤儿进程,并进一步被系统中管理孤儿进程的进程收养并清理。
#秋招##嵌入式##嵌入式笔面经分享#我打算把自己整理的八股文笔记、面试经验、项目经验、简历修改经验等等,分享给大家。之前准备找工作那会,很多付费的东西,质量参差不齐,我打算在牛客创建一个免费的专栏,分享整理的这些内容,今天这个是第一篇文章,对于找工作的人提供一份帮助就行。