嵌入式高频八股:操作系统篇

启动流程

为什么两次初始化DDR

  1. 第一次是BOOTLOADER初始化DDR,使其从不可用到可用,保证可以正常的引导和加载操作系统,会将UBOOT的BL1从FLASH中拷贝到DDR中执行。
  2. 第二次是LINUX启动过程中对DDR进行更加细致的初始化,并且将DDR的内存配置与内核的内存管理需求匹配。

UBOOT启动流程

【ARM-LINUX开发】U-BOOT启动过程--详细版的完全分析 - ZHANGPYI - 博客园 (CNBLOGS.COM)

中断

中断类型

  • 中断
    • 可屏蔽
    • 不可屏蔽
  • 异常
    • 陷阱(TRAP) 系统调用、信号
    • 故障(FAULT) 缺页异常
    • 错误

GIC中三种中断

  • SPI 共享外设中断
  • PPI 私有外设中断
  • SGI 软件生成中断

SGI通过软件向GIC的SGIR寄存器写值来产生中断,GIC根据内容分发给特定核心

ISR中断服务函数

ISR(INTERRUPT SERVICE ROUTINE),即中断服务程序,是处理器在响应硬件中断时执行的特殊函数。它用于处理硬件事件,并在完成后返回正常的程序执行流。ISR是嵌入式系统和实时操作系统中的关键组件。

  • 快速执行
  • 不使用阻塞操作
  • 避免使用全局变量
  • 嵌套中断

软中断

LINUX中断(INTERRUPT)子系统之五:软中断(SOFTIRQ)-阿里云开发者社区 (ALIYUN.COM)

软中断与软件中断

软中断 软件中断
用途 LINUX内核提供的延时处理机制
分离较为复杂的工作推迟处理
系统调用、异常处理、虚拟化环境通信
触发方式 硬中断或者其他部分触发 特定指令触发
执行环境 特定调度时机 中断上下文

硬件怎么告诉驱动信息来了

中断。继续回答中断的流程。一般是通过一个硬件引脚,发送给GIC控制器,然后捕获这个中断信号,GIC管理优先级排序和消息分发给对应的CPU,然后CPU会进入中断处理函数处理,这个函数一般是驱动注册的回调函数去区里,然后清除掉中断,CPU恢复继续去执行

中断初始化时需要设备树信息,是不是需要去解析它

是的。 在嵌入式系统中,设备树通常用于描述硬件配置,如中断控制器、GPIO、中断号等。当一个设备驱动初始化时,它会从设备树中提取相关的硬件信息,这包括中断相关的属性。具体步骤大致如下:

  1. 设备树节点描述:设备树中每个设备节点都可能包含中断信息,通常使用属性如 INTERRUPTSINTERRUPT-PARENT。中断控制器也通过设备树节点描述其类型和配置。
  2. 解析设备树:内核启动时,内核设备树解析器会根据设备树的内容建立硬件信息,特别是中断控制器的信息。然后设备驱动可以通过特定的 API 来读取和解析设备树中的中断号和触发类型。
  3. 调用 DT 解析 API:LINUX 内核提供了相关 API,比如 OF_IRQ_GET()IRQ_OF_PARSE_AND_MAP() 等,这些函数帮助驱动从设备树中提取和映射中断号。驱动程序会调用这些 API 获取设备树中的中断信息。
  4. 中断注册:在解析出设备树中的中断信息后,驱动程序会使用 REQUEST_IRQ() 等 API 注册中断处理函数。

中断中为什么不可以睡眠?

面试官:为什么在中断里不能 SLEEP | LINUX 内核 - 知乎 (ZHIHU.COM)

  1. 中断是在中断上下文中,与任何的进程上下文无关
  2. 内核代码里有大量的 CRITICAL SECTION (临界区),如果想要支持 CALL SCHEDULER 的话,那么所有的 CRITICAL SECTION 都必须得禁用中断,否则硬件中断一旦来临系统就会出现 RACE CONDITION,接下来大概率是死锁。但是这样的中断响应延迟就很大。

内存管理

内存碎片的类型

  • 外部碎片:内存有足够的内存,但是由于空闲空间被分成多个不连续小块,无法满足分配大的内存空间
  • 内部碎片:分配的内存块比实际需求大的多,多出来的部分无法使用

内存碎片产生的原因、有哪些场景产生、怎么解决

产生原因:

  • 外部碎片:内存有足够的内存,但是由于空闲空间被分成多个不连续小块,无法满足分配大的内存空间
  • 内部碎片:分配的内存块比实际需求大的多,多出来的部分无法使用

场景:

  • 频繁的动态分配和释放内存
  • 操作系统分配内存可能产生碎片
  • 虚拟内存系统将物理内存映射到虚拟地址空间时

解决方式:

  • 优化算法
    • 首次适配(FIRST FIT):找到第一个能满足要求的空闲块进行分配。
    • 最佳适配(BEST FIT):找到最接近所需大小的空闲块进行分配,减少外部碎片。
    • 最坏适配(WORST FIT):找到最大的空闲块进行分配,尝试保留大块空间以减少未来的外部碎片。
  • 伙伴算法
  • SLAB算法
  • 垃圾回收
  • 内存压缩:适当的时候进行整理
  • 内存池

伙伴算法的优缺点

优点

  • 分配速度快,分割和合并效率简单高效
  • 减少外部碎片
  • 内存对齐 缺点
  • 依旧存在内部碎片
  • 内存利用率不高(内部碎片的问题)
  • 复杂性

环形缓冲区怎么判断空、满

环形缓冲区有BEGIN END两个指针,当

  • 空 BEGIN=END
  • 满 BEGIN->NEXT=END

内存泄漏

总的来说一句话,分配了内存没有释放。

  • NEW 没有FREE
  • 循环引用,计数器无法归零
  • 丢失指针

解决办法:

  • 分配后释放
  • 智能指针
  • 避免循环引用

工具:

  • ADDRESSSANITIZER
  • VALGRIND

内核空间与用户空间之间的内存拷贝

通过COPY_TO_USER()COPY_FROM_USER,在拷贝的时候会进行地址的检测,是否指向有效的用户空间内存区域,以及确保访问不会越界。然后操作系统内核会使用 CPU 的特权模式来访问用户空间的内存地址。因为进入内核的时候页表不会改变,依旧用的是用户进程的页表(所有进程的内核空间映射是同一个位置,用户态进入内核态不需要切换页表)。这些地址通过 MMU 进行转换,映射到物理内存,然后内核通过物理内存地址进行读写操作。由于用户空间的内存地址可能是虚拟地址,内核需要通过页表进行转换,找到对应的物理地址。这个过程是由硬件 MMU 和操作系统联合完成的。

总结:通过特定函数,内核以特权模式直接向用户空间虚拟地址指向的物理地址进行拷贝。

应用层随便写个地址,内核是怎么检测出异常的

进程在创建的时候会先将分配好自己所需要的虚拟地址空间,但是此时并没有对实际的物理地址分配映射,后续需要的时候才会分配,所以可以区分下面两种来对检测异常做解释:

  • 缺页异常:发现需要访问的地址在已经分配的虚拟地址空间内,但是没有映射到物理地址,就会触发缺页异常,然后分配物理地址做出映射,放到页表中方便后续使用。
  • 段错误:发现需要访问的地址超出了虚拟地址的空间,或者超过了堆栈的范围,或者是访问的页面权限不符,就会认为是一个错误地址。

IOMMU的作用与意义

作用:

  1. 地址转换:
    • IOMMU 为 I/O 设备提供虚拟地址空间支持,类似于 CPU 使用 MMU 来管理进程的虚拟地址空间。IOMMU 将设备发出的虚拟地址转换为物理地址,使设备可以访问系统内存,而不需要知道物理内存的实际布局。
    • 这种地址转换还允许设备在被重新配置时,不需要修改其所使用的内存地址,只需修改 IOMMU 的映射即可。
  2. 内存保护:
    • IOMMU 提供了一个安全层,通过限制设备可以访问的内存区域,防止设备意外或恶意地访问其他进程或内核空间的内存。
    • 这种保护对防止 DMA(DIRECT MEMORY ACCESS,直接内存访问)攻击特别重要,因为攻击者可能试图利用 DMA 设备直接访问内存,从而绕过操作系统的安全机制。
  3. 设备隔离:
    • 在虚拟化环境中,IOMMU 可以帮助实现虚拟机对物理设备的隔离。它允许虚拟机使用物理设备的虚拟化版本,同时确保这些设备只能访问分配给它们的内存区域。
    • 这种隔离对于确保虚拟机之间的安全性至关重要,因为它防止了一个虚拟机能够通过设备访问其他虚拟机的内存。
  4. 提高系统性能:
    • 在多核和多设备的复杂系统中,IOMMU 可以优化内存访问路径,使得 I/O 操作更高效,减少 CPU 处理内存访问的负担。
    • 通过 IOMMU,设备可以直接访问系统内存,而无需通过中介或额外的内存拷贝,这种直接访问(DMA)可以显著提高数据传输速率。

意义:

  1. 安全性增强:
    • IOMMU 是现代计算机系统安全架构中的关键组成部分。它通过防止设备对不安全内存区域的访问,大大提高了系统的安全性。尤其是在

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

1. 自我介绍:高通、Oppo(sp)、vivo(sp)、小米(ssp)、荣耀(26k*12+80k)、华子(报批中)、美团、韶音、经纬恒润、乐鑫、中兴、TP 2. 内容: 1.嵌入式学习的资料和路径 2.所有面试的题目和解答(持续更新)、对评论的快速解答 3.各种碎碎念 3.整理不易,buy me coffee☕️,为了回馈牛客和各个粉丝,文章都会先试读几天,热度过了再收录~

全部评论

相关推荐

各位前辈好,先说声抱歉,可能又是一篇“求骂醒”的帖子,但我真的需要一个方向。我的情况比大多数人都糟糕:双非软件工程,大四,马上毕业了,0实习经历,0工作经验。秋招根本没参加,原因很傻——我一头扎进了一个自己觉得“挺有意思”的项目里,天真的以为把项目做好工作自然会找上门。现在春招也快结束了,我才如梦初醒,发现简历投出去基本石沉大海。我没有什么能拿出手的背景,唯一能说的就是这个从后端到前端全栈独立开发的电影推荐平台。我知道在各位前辈眼里这大概率就是个小玩具,但我确实是下了功夫去琢磨的,它不是什么网上扒的代码,下面这些是我自己琢磨并落地的东西:项目概况:Spring Boot + MyBatis-Plus + Redis + JWT + MySQL + Vue3(前端是AI辅助生成的)我自己觉得花了心思的几个点:1. 推荐算法落地:没有照搬别人的推荐逻辑。我是基于用户多维行为数据(评分、收藏、浏览时长)去计算标签权重,然后用“评分×log(热度+1)”的公式做加权排序;冷启动场景用热门数据兜底。推荐结果用Redis的ZSet缓存,用户行为一变化就主动删缓存触发重算。2. 缓存体系设计:不是那种“面试八股文背完就扔”的表面理解。我实际遇到了缓存穿透和击穿的问题,然后自己用空值缓存+逻辑过期去解决。热门电影定时预热、批量查询用multiGet减少IO次数,还封装了MyCacheUtils通用模板,让整个项目其他模块也能复用这套缓存逻辑。3. 并发与一致性:用Redis的SET NX EX实现了收藏/点赞的分布式锁,key精确到“用户+操作对象”级别,不是粗粒度的一锁全锁。异常回滚时Redis和MySQL数据一致性问题也思考并落地了。验证码的原子性校验用了Lua脚本来保证。4. 性能是真实数据:我用JMeter做了2000并发的压测,引入Redis缓存体系后,推荐接口平均响应从6466ms降到155ms,吞吐量翻了一倍,缓存命中率干到98%以上。这些数据不是编的,是我自己反复调优跑出来的。说实话,做完这些的时候,看着压测报告我是挺兴奋的,觉得“这也算出活儿了吧”。但现实是,0实习好像成了我简历上的原罪,很多公司直接筛选条件就把我过滤了。所以我想跪求各位前辈指点我几个问题,每一条我都认真看、认真执行:1. 关于简历:0实习的应届生,还有资格谈“项目亮点”吗?我这项目,是不是在专业面试官眼里就是一个“低配版培训项目”?如果这个项目还有救,该怎么在简历上呈现,才能让HR或者面试官至少愿意给我一个电话面试?如果没有,一个0实习的应届生到底该在简历上写什么?2. 关于面试:如何用项目细节证明“我虽然没实习但真的能干活”?我挺怕面试官看到我没有实习经历就直接失去兴趣。真到了面试那一步,我该怎么引导对话,用上面这些技术细节去对抗“没实习=没工程经验”的刻板印象?比如缓存那块,怎么从“我解决了击穿”讲出一个有技术判断力和工程思维的完整故事?3. 关于求职策略:错过了黄金窗口期,现在该冲什么样的公司?大厂我肯定不奢望了。现在这个时间点,我应该去投那些小公司和外包吗?要不要把薪资预期降到最低先入行再说?对于0实习的应届生,什么样的公司是真的有机会让我进去学技术、积累经验的?4. 关于未来:如果现在直接找不到工作,我该怎么办?这段时间我想好了,如果实在是找不到研发岗,我要不要去干测试或者运维先入行?还是找家小公司被压榨一年攒个经验?还是干脆先找个其他工作边干边学等下一轮秋招?我什么建议都能接受。我知道自己起步晚了,代价得自己扛。现在唯一能做的就是面对现实,然后找到一条最有可能逆袭的路。希望前辈们能给我指个方向,即使简单几句“没救了”或者“还能救,去做XXX”我都非常感激。
jiestart:这简历肯定没面试的,你得包装个实习再加一个agent项目才有希望
点赞 评论 收藏
分享
万物DP:目前可以说没机会了,offer在4月都发完了。把实习用AI改一改投中小厂吧
点赞 评论 收藏
分享
评论
10
96
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务