虫虫首页| 资源下载| 资源专辑| 精品软件
登录| 注册

您现在的位置是:首页 > 技术阅读 >  操作系统面经

操作系统面经

时间:2024-02-14

前一段时间面了一些试,这里总结一下关于操作系统的面经,我简历上写了一个操作系统相关的项目,所以面试的问题可能与平常的八股面试题等等有一些差异,更加偏向具体细节和实现。这里就面试遇到的操作系统相关问题以及我自己的想法整理一下,可以参考参考,有什么问题也还请批评指正

这个是实际问到我的问题

自己引申出来的问题

黑色普通文字是我的“回答”或者与面试官闲聊的内容

启动

  • 启动过程,BIOS->MBR->Bootloader->OS,多 CPU 情况下 BSP 启动 APs,叙述每个阶段做的主要事情。
  • 上电那一刻,CS:IP = 0xf000:0xfff0,此地址上的 16 字节是个跳转地址:jmp f000:e05b(据然还真问到了具体跳转地址)
  • BIOS
    • 干了些啥事,自检程序,将 MBR 加载到 0x7c00
    • 提问其他的固件方面的知识,BIOS,UEFI等,不太了解
  • 实模式、保护模式
    • 区别,前者16位,地址线只用了20根,后者解开限制,前者的段寄存器里面是段基址,后者段寄存器里面是段选择子
    • 为什么有实模式,兼容?
    • 如何进入保护模式,构建GDT、打开A20,CR0.PG = 1
  • MBR
    • MBR 构成,引导程序->64字节分区表->魔数(0x55和0xAA)
    • 在哪儿,启动盘最开始那个扇区
    • 加载到哪儿,加载到 0x7c00
    • 主要干的事情,根据分区表找到一个活动分区,然后加载 Bootloader
    • 如何判断是否是启动盘,魔数 0x55 和 0xAA
  • 开启分页机制(x86),构建页表; 页表地址给 CR3; CR0.PE = 1
  • BSP 启动 AP 过程(x86,中断控制器为APIC),主要通过 LAPIC 发送 INIT-SIPI-SIPI 消息... 详见 Multiprocessor Specification
  • OS 第一个 init 进程做了些什么
    • xv6 里面打开 0 1 2 号文件
    • fork 出 shell
    • 然后 wait(等待孤儿进程过继给init)
    • 提问现在的 Linux 里面干了些什么,有简单看了看,有些复杂待研究
  • 汇编和 C 交互的一些问题,遵循调用约定,全局变量等在汇编时就要处理好

内存管理

  • 寻址方式,x86 段基址:段内偏移

    • 实模式下段寄存器为实际的段基址,保护模式下为段选择子
  • 分段分页特点,为什么分页

    • 分段同类型数据放在一起,分页逻辑上连续物理上分散实现离散化存储
    • x86 有段寄存器,硬件上原生支持分段,其他架构硬件上似乎不支持
    • x86 可以设置平坦模式,“隐藏”分段
  • 地址转换过程,段级转换(GDT)、页级转换(查页表)

  • GDTR 中存放 GDT 的线性地址,CR3 里面存放页目录的物理地址,页表项里面存放的也是物理地址。

  • 物理内存管理,目前 xv6 里面简单的空闲链表法,引申到伙伴系统 Slab 分配器,不管什么地方,空间管理的方式一般就两种,链表和位图,万变不离其宗。

  • 虚拟地址空间如何布局的

    查看源图像
  • 堆、共享区等的管理方式,xv6 里面堆的管理方式也是链表,看侯捷老师关于 C++ 内存部分讲解,也是类似伙伴系统的思想,申请空间过大时也是 mmap 在共享区分配空间

  • 堆空间分配相关,C++ new 出来的,能否用 free 返回,一个 C++ 相关的问题,从堆分配的空间有个头部,头部记录了大小信息,而 new 不一定,所以最好不要这么干。

  • 缺页异常三种,写时复制、延迟分配、页面置换

    • 写时复制的实现思想,要点:利用页表项保留位设置为COW标志位,复制内存时(主要fork)不实际复制内存,只复制页表,并将COW=1,R/W 设置为只读,其他共享计数、回收等略,详见 xv6 写时复制实现
    • 延迟分配,页表项全0,只在页表中建立了映射,并未实际分配物理内存,详见 xv6 延迟分配实验
    • 页面置换,页表项非空,页表项 P = 0;常见页面置换算法;页面置换交换区实现方式,具体实现有些复杂,详见 ucore 的例子,有配套的手册讲解。
  • Linux kmalloc 的特点,分配的物理内存连续

IO 管理/中断

  • 中断、异常区别,外、内

  • 中断异常详细分类,据 CSAPP 中断、陷阱、故障、终止

  • 中断、异常返回的 PC 是什么,据CSAPP,中断、陷阱下一条,异常(故障)可能返回当前 PC,终止不会返回

  • 中断过程

  • 中断控制器干了什么事,见上图
  • 如何定位的中断服务程序,见上图
    • 上图 x86 的情况是硬件识别,向量中断的方式
    • 还有软件识别的方式,跳到一个固定地址,然后再查询异常状态寄存器看是什么异常,再跳到特定的处理程序,一般精简指令集这么干。
  • 开关中断的事,一般我们说中断时保存上下文前要关中断,x86 下,关中断就是 EFLAGS 的 IF = 0
  • 系统调用过程
    • 没有中断控制器这个过程,其他阶段基本相同
    • 传参两种方式,寄存器,压栈(进入内核后从上下文中的栈指针寄存器获取用户态栈顶地址)
    • x86下系统调用可以用中断门实现,也可以使用陷阱门实现,使用中断门进入中断自动关中断,如果使用陷阱门则不会自动关中断,这是二者唯一的区别
  • 按下一个键到显示在屏幕上,键盘中断 + 显卡、写显存 过程,太多略,详见捋一捋控制台的输入输出
  • DMA 过程,不是很清楚,百度google,我也是搜的。
  • 磁盘寻址,CHS(柱面磁头扇区)、LBA(逻辑块地址),实际上似乎不是想问这个,但面试官当时也没说清楚就下一个问题,emm??????
  • 内核态、用户态的理解,实际上就是特权级,RPL、CPL、DPL 三者之间不同情况下的各种比较变化,特复杂。
  • 用户态到内核态栈的变化x86 下根据 TR 可以找到 TSS,TSS 里面有内核栈的 CS 和 ESP;RISC-V 下 sscratch 有内核上下文的地址

文件管理

  • 分区布局,引导块->超级块->inode、位图、数据区
  • 写磁盘如何保证数据一致性,设计日志层(当时某度二面,全程基本就讨论这个)
  • inode、路径、目录、目录项、全局文件表和文件结构体、进程打开文件表和文件描述符等概念以及它们之间的关系
  • open close dup write read 等常见系统调用,做了什么事情
    • 比如 open 的要点分配文件结构体、文件描述符。
    • 这个函数只是用户接口,整个是一个是系统调用过程。
  • inode 相当于树形结构的索引、假如设计为哈希索引,如何设计,Cache 缓存,优劣等等讨论
  • 硬链接、软链接区别
    • 硬链接与目录项挂钩,多个目录项一个 inode 一个文件
    • 软链接是个文件有自己的 inode,文件内容是路径
  • 目录项缓存,Linux 使用目录项缓存 dentry cache 缓存提高目录项对象的处理效率,我也只知道这个东西,待研究
  • 命令获取某个目录下的文件数量

进程

  • 谈进程、线程、协程的理解,聊区别简易设计
  • 第一个进程干了些什么事,见前
  • 切换过程,重点换上下文、换栈
  • 为什么切换进程比切换线程慢,除了进程“体量”大,另外切换进程要切换页表,切换页表要刷新TLB
  • 切换时机,自己阻塞让出 CPU,时间片到了
  • 状态转换,发生中断时进程状态如何转换,时间中断设置为就绪,其他情况在 xv6 里面没变,Linux 不了解。
  • fork 实现
  • exec 实现
  • 孤儿进程:父进程先退出了,过继给 init 进程;僵尸进程:子进程退出父进程没有wait
  • 僵尸进程孤儿进程的理解,进程要退出时调用 exit,exit 会关闭文件等资源,另一部分资源是父进程调用 wait 来释放,wait 释放子进程的栈、上下文、页表、任务结构体等资源。
  • 如何解决僵尸进程,父进程总会退出,那么在 exit 中检测是否有将是状态的子进程,如果有,将其过继给 init 进程,然后唤醒 init 让它来处理。
  • 进程间的通信,信号、信号量、共享内存、消息队列、匿名管道、有名管道,聊简单设计
  • 调度算法,Linux 的 CFS
  • Go 的协程模型,不太了解卒
  • 关于进程的命令,如何查看进程状态等等

其他

  • 锁的实现,自旋锁和休眠锁
  • 自旋锁,while 循环
  • 内存一致性,硬件如何支持的原子操作,聊了指令 Lock 锁总线等等,CAS、Acquire/Released 等
  • 休眠锁涉及进程的休眠唤醒机制如何实现
  • Cache 缓存一致性,MESI
  • 设计操作系统需要研究研究设计模式,所以设计模式??????
  • 复杂指令集和精简指令集区别
  • elf 文件格式介绍,可装载段,装载地址,filesz、memsz 等

好了,本文就到这里了,有什么问题还请批评指正。


这里有 一个优质的C++学习圈 等你加入,来一起钻研C++吧。