目录
14.一个C/C++程序从开始编译到生成可执行程序的完整过程?
1.进程、线程、协程的区别与联系?
进程 | 线程 | 协程 | |
定义 | 资源分配和拥有的基本单位 | 程序执行的基本单位 | 用户态的轻量级线程,线程内部调度的基本单位 |
切换情况 | 进程CPU环境(栈、寄存器、页表等)的保存以及新调度的进程CPU环境的设置 | 保存和设置程序计数器、少量寄存器和栈的内容 | 先将寄存器上下文和栈保存,等切换回来的时候再进行恢复 |
切换者 | 操作系统 | 操作系统 | 用户 |
切换过程 | 用户态->内核态->用户态 | 用户态->内核态->用户态 | 用户态 |
调用栈 | 内核栈 | 内核栈 | 用户栈 |
拥有资源 | CPU资源、内存资源、文件资源等 | 程序计数器、寄存器、栈和状态字 | 自己的寄存器上下文和找 |
并发性 | 不同进程之间切换实现并发、各自占有CPU实现并行 | 一个进程内多个线程可以并发执行 | 同一时间只能执行一个协程,其他协程处于休眠,适合对任务进行分时处理 |
系统开销 | 切换虚拟地址空间、内核栈、硬件上下文、页表,开销很大 | 切换时需保存和设置少量寄存器内容,开销小 | 直接操作栈基本没有内核切换开销,可以不加锁的访问全局变量,上下文切换很快 |
2.进程、线程的比较?
1)线程启动速度快
2)线程系统开销小
3)使用线程需要处理数据一致性问题
4)同一进程中的线程共享堆、全局变量、静态变量、指针、引用、文件等,线程独自拥有栈
3.进程和线程的区别?
1)线程是程序执行的基本单位;进程是拥有资源的基本单位;
2)一个进程内的多个线程可以并发;多个进程可以并发
3)线程不拥有系统资源,但可以共享进程的资源;进程是拥有资源的基本单位
4)线程的创建与销毁只需要处理PC值、状态码、通用寄存器值、线程栈和指针;进程创建和销毁需要重新分配和销毁task_struct结构
4.一个进程可以创建多少线程?
1)如果是32位系统:用户态的虚拟空间有3G,如果创建一个线程需要10M,那么一个线程只能创建300个线程;
2)如果是64位系统:用户态的虚拟空间达到有128T,理论上不会受虚拟空间大小的限制,但是会受到系统的参数和性能的限制。
5.外中断和异常有什么区别?
外中断指由CPU执行指令以外的事件产生的,如I/O中断、时钟中断等;
异常指由CPU执行命令的内部事件产生的,如地址越界、除0操作等。
6.进程的调度算法有哪些?
1)先来先服务:非抢占式,按照进程的请求顺序进行调度。有利于长作业,不利于短作业。
2)短作业优先:非抢占式,按进程估计运行时间的最短顺序调度。长作业可能会饿死,如果一直有短作业到来,那么长作业就一直不会被调度。
3)最短剩余时间优先:短作业优先的抢占式版本,按剩余运行时间的最短顺序调度。当一个新的作业到达时,其运行时间会和当前进程的剩余时间作比较,时间更少则挂起当前进程,运行新的进程,否则等待。
4)时间片轮转:将所有就绪进程按照先来先服务的原则排成队列,每次调度时从队首取一个进程,给其分配一个时间片的CPU时间。
5)优先级调度:给每个进程分配优先级,按优先级调度。为防止低优先级的进程永远等不到调度,可以按照进程等待时间提高进程的优先级。
6)多级反馈队列:设置多个队列,每个队列的时间片不同,如1、2、4、8...。进程在第一个队列没有完成,则就放到下一个队列的队尾,最上层队列的优先级最高,当上一个队列没有进程时,才调度当前队列的进程。可以将该调度算法看作是时间片轮转+优先级调度的结合。
7.Linux下进程间通信方式有哪些?
1)无名管道(内存文件):半双工通信,只能在有具有亲缘关系的进程间通信,如父子进程。
2)有名管道(FIFO文件,借助文件系统):半双工通信,可以在没有亲缘的进程间通信。
3)信号:用于通知进程某个事件发生,如CTRL C。
4)信号量:一个计数器,用来控制多个进程对共享资源的访问。它经常作为一种锁,实现进程、线程对临界区资源的同步和互斥访问。
5)socket:适用于相同机器或不同机器的进程间通信。
6)共享内存:映射一段内存空间,可以被其他进程访问。
7)消息队列:存放在内核中的有消息的链表,它被消息队列的标识符所标识,克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
8.Linux下同步机制?
POSIX信号量:可以用于进程、线程同步
POSIX互斥锁+条件变量:只能用于线程同步
9.虚拟地址转换物理地址的过程?
1)CPU给出逻辑地址,由硬件计算出页号和页内偏移量,将页号和快表中的页号比较。
2)如果快表中存在相同的页号,说明要访问的页表项在快表中有副本,则直接取出页表项对应的内存块号,将内存块号与页内偏移量拼接成物理地址,访问该内存单元。因此,如果在快表中命中,则只要访问内存一次。
3)如果快表没有命中,则需要访问内存中的页表,找到对应的页表项,得到内存块号,然后和页内偏移量拼接成物理地址,最后访问该内存单元。因此快表没有命中,则会访问两次内存。在找到页表项后,需要将该页表项加入到快表中,防止后续再次访问。若快表满了,则需要替换旧的页表项。
10.内存交换和内存覆盖的区别?
交换技术主要在不同的进程(或作业)之间进行;覆盖则在同一个进程中进行。
11.动态分区分配算法有哪些?
1)首次适应算法:每次从低地址开始寻找第一个满足大小要求的空闲分区。
实现方法:空闲分区以地址递增的顺序排序,每次顺序查找空闲分区中第一个满足大小要求的分区。
2)最佳适应算法:优先适应更小的能满足大小要求的空闲分区。
实现方法:将空闲分区按容量大小递增排序,每次顺序查找空闲分区中第一个满足大小要求的分区。
缺点:容易产生内部碎片。回收分区后需要重新按照内存大小排序。
3)最坏适应算法(最大适应算法):优先分配最大的空闲分区。
实现方法:将空闲分区按容量大小递减排序,每次顺序查找空闲分区中第一个满足大小要求的分区。
缺点:容易造成较大的连续空间的分区被分配完,导致“大进程”到达后没有内存可以使用。回收分区后需要重新按照内存大小排序。
4)邻近适应算法:由于首次适应算法每次从头开始寻找分区,增加了查找开销,所以该算法每次从上一次查找结束的位置查找。
实现方法:空闲分区以地址递增的顺序排序,每次从上一次查找结束的位置查找,找到第一个满足大小要求的分区。
缺点:低地址和高地址都有相同的概率被使用,所以导致高地址的大分区更可能被使用,最后导致没有大分区可用。
综上得出,首次适应算法效果最好。
12.什么是虚拟技术?
虚拟技术将一个物理实体转换成多个逻辑实体。
主要有两种虚拟技术:时分复用、空分复用
多进程或者多线程在同一个处理器上并发执行使用了时分复用技术。
虚拟内存使用了空分复用技术将物理内存抽象为地址空间,每个进程都有各自的地址空间。地址空间映射在物理内存,地址空间的页不需要全部在物理内存中,当使用一个不在物理内存的页时,执行页面置换算法,将页面置换到物理内存中。
13.进程状态的切换有哪些?
就绪状态、阻塞状态、运行状态。
就绪状态的进程获得CPU转为运行状态,CPU时间片用完后转换为就绪状态。
运行状态的进程因缺少资源转换为阻塞状态,获得资源后转为就绪状态。
只有就绪状态和运行状态可以相互转换。
14.一个C/C++程序从开始编译到生成可执行程序的完整过程?
1)预处理:主要处理#开头的预编译指令,生成.i或.ii文件。
2)编译:把预处理之后生成的.i或者.ii文件进行一系列词法分析、语法分析、语义分析及优化后,生成汇编代码文件。
3)汇编:将汇编代码文件转换成机器可执行的指令,产生目标文件.o文件。
4)链接:将不同的源文件产生的目标文件进行链接,形成可执行程序。
15.进程同步的四种方法?
临界区、互斥量、信号量、管程。
16.操作系统在对内存进行管理的时候需要做些什么?
1)负责内存的分配与回收
2)提供某种技术从逻辑上对物理内存进行扩充
3)提供地址转换功能,将逻辑地址和物理地址相互转换
4)提供内存保护功能,保证各个进程在各自的存储空间内运行,互不干扰
17.线程通信方式?
Linux:信号、信号量、锁、条件变量
Windows:全局变量、message消息机制、CEvent对象。
18.虚拟内存的目的?
为了让物理内存扩充成更大的逻辑内存,让程序拥有更多的可用空间。操作系统将物理内存抽象成地址空间,每个程序拥有自己的地址空间,这个地址空间被分割成多个块,每一块成为页。每个页映射到物理内存中,不需要将所有的页都映射在内存中,当程序引用到不存在的页后,只需将缺失的部分重新加载到物理内存中就行。
19.介绍几种典型的锁?
1)读写锁:支持同时进行读操作,写操作必须互斥,写操作优于读操作。
2)互斥锁:一次只能有一个线程拥有互斥锁,其他线程等待,通常和条件变量一起使用。
3)自旋锁:如果进程/线程无法获得锁,不会立即放弃CPU,而是会不断尝试获取锁,直到获取为止。应用于加锁时间很短的场景,这个场景下效率比较高。
20.有哪几种线程锁?
1)互斥锁和条件变量
2)自旋锁