前言
地平线面经
题目
- 写应用程序如果突然停止,做一些什么操作能够让系统再一次跑的时候避免
在编写应用程序时,如果突然停止,你可能希望采取一些措施来确保系统能够在再次运行时避免出现问题。以下是一些建议的操作:
异常处理:在应用程序中实现适当的异常处理机制。捕获可能导致应用程序崩溃的异常,并相应地处理它们,例如记录错误日志、释放资源、恢复状态等;
保存状态:在应用程序停止之前,尽可能保存应用程序的状态。这包括保存用户的工作进度、当前任务的状态、配置设置等。可以将这些状态保存到文件、数据库或内存中,以便在应用程序重新启动时恢复;
定期保存数据:如果应用程序涉及到处理大量数据,建议定期将数据保存到持久存储中。这样即使应用程序意外停止,也可以最大程度地减少数据丢失;
记录错误信息:在编写代码时,考虑到各种异常情况和边界条件,尽可能使应用程序更加健壮和稳定。避免出现可能导致应用程序崩溃的代码路径或逻辑错误;
实现健壮性和稳定性:在编写代码时,考虑到各种异常情况和边界条件,尽可能使应用程序更加健壮和稳定。避免出现可能导致应用程序崩溃的代码路径或逻辑错误
- 内存泄露检测工具的原理
kmemleak通过追踪kmalloc(), vmalloc(), kmem_cache_alloc()等函数,把分配内存的指针和大小、时间、stack trace等信息记录在一个红黑树中,等到调用free释放内存时就把相应的记录从红黑树中删除。也就是说红黑树中的记录就是已经分配出去但尚未释放的内存,其中有些内存尚未释放是因为还在被使用,这属于正常情况,而不正常的情况,即真正“泄漏”的内存都是不会再被使用的,那么如何找出泄漏的内存呢?kmemleak缺省每10分钟对内存做一次扫描,寻找内存中有没有红黑树中记录的地址,如果某个地址在内存中找不到,就认为这个地址是无人引用的,已经被泄露的内存没有任何方法可以把其地址传递到内存释放函数中。最后把红黑树中所有被视为泄露的内存的相关信息(地址,大小,申请者,申请时间等)输出到/sys/kernel/debug/kmemleak接口。
- 内存越界检测工具的原理
Kasan 的原理是利用“额外”的内存来标记那些可以被使用的内存的状态。这些做标记的区域被称为影子区域(shadow region)。了解 Linux 内存管理的读者知道,内存中的每个物理页在内存中都会有一个 struct page 这样的结构体来表示,即每 4KB 的页需要 40B 的结构体,大约 1% 的内存用来表示内存本身。Kasan 与其类似但“浪费”更为严重,影子区域的比例是 1:8,即总内存的九分之一会被“浪费”。用官方文档中的例子,如果有 128TB 的可用内存,需要有额外 16TB 的内存用来做标记。
做标记的方法比较简单,将可用内存按照 8 子节的大小分组,如果每组中所有 8 个字节都可以访问,则影子内存中相应的地方用全零(0x00)表示;如果可用内存的前 N(1 到 7 范围之间)个字节可用,则影子内存中响应的位置用 N 表示;其它情况影子内存用负数表示该内存不可用。
- I2C驱动编写时,如果出现异常怎么拍错
检查硬件连接:确保I2C设备的连接正确,包括电源、SDA、SCL,使用示波器或逻辑分析仪检查信号波形,确保设备之间的通信正常;
检查设备地址:确保正确设置了要访问的I2C设备的地址。通常每个I2C设备都有唯一的地址,如果地址设置不正确,可能会导致无法正确访问设备;
检查时序:确保在正确的时序下发送I2C命令和数据,包括起始条件、停止条件、数据传输等。
调试驱动代码:使用printk、串口调试等工具,对驱动程序进行调试,检查驱动程序的逻辑是否正确,是否正确处理了各种情况和异常情况;
查看日志和记录:查看系统日志、驱动程序日志或记录文件,寻找任何可能的错误消息或异常情况。记录发生异常的时间、环境和条件,已帮助排除问题;
验证代码逻辑:检查驱动程序的代码逻辑,确保没有逻辑错误或边界情况未处理。检查是否正确处理了一场情况,例如设备不想赢、通信超时等;
联系供应商或社区:如果遇到无法解决的问题,可以与硬件供应商或相关的开发社区联系,寻求帮助和支持。
- 说一下I2C驱动编写有哪些操作
初始化:在驱动程序中进行I2C总线初始化,包括设置时钟频率、配置GPIO引脚、启用I2C控制器等;
设备识别:在初始化期间,可以扫描总线上的设备,识别连接到总线上的每个设备的地址和类型。通过发送读取命令执行,查看相应或确定设备存在;
设备访问:实现对设备的读取和写入操作,包括设置设备地址、发送数据、接收数据等操作。可以根据设备规格和需求实现特定的读写功能;
错误处理:在驱动程序中实现错误处理机制,处理可能发生的错误情况,例如设备无响应,通信超时,传输错误等。包括检查返回的错误码和标志,并采取相应的措施来解决问题;
中断处理:如果需要使用中断来处理I2C数据传输, 需要实现中断处理程序,以便在中断事件发生时执行相应的操作;
时序控制:确保在正确的时序下发送 I2C 命令和数据。这包括发送起始条件、停止条件、数据传输等操作,确保与设备之间的通信是按照规范进行的;
电源管理:在驱动程序中实现适当的电源管理功能,例如启用和禁用设备,进入低功耗模式,以最大限度地降低功耗并延长设备的电池寿命;
性能优化:对驱动程序进行优化,以提高性能和效率,包括减少通信延迟、最大限度地减少CPU和总线资源的使用等;
调试和日志记录:在驱动程序中添加调试代码和日志记录功能,以便在出现问题时能够更容易地诊断和解决问题。包括记录重要的事件、错误消息和异常情况,以及输出调试信息和状态;
测试和验证:对编写的驱动程序进行测试和验证,确保其功能和性能符合预期。包括编写单元测试、集成测试和系统测试,并确保驱动程序在各种条件下都能正常工作。
- 虚拟内存和物理内存的区别
物理内存:是计算机系统中实际存在的内存模块或芯片,用于存储程序和数据。它是计算机直接访问和使用的内存资源
虚拟内存:是操作系统为了提供更大的地址空间和更好的内存管理而提供的一种机制,允许程序访问一个比实际物理内存更大的地址空间,并且可以通过将内存中的数据存储在磁盘上来实现。
大小上:
- 虚拟内存的大小可以比物理内存更大,发送 I2C 命令和数据。这包括发送起始条件、停止条件、数据传输等操作,确保与设备之间的通信是按照规范进行的;
- 物理内存的大小是实际可用的内存容量,通常是由计算机硬件决定的
映射关系:
- 虚拟内存是通过地址映射机制与物理内存进行交互的。操作系统会将虚拟地址映射到物理地址上,并负责将虚拟内存页面与物理内存页面进行交换;
- 物理内存直接存储程序和数据,不需要经过地址映射过程
访问速度:
- 虚拟内存的访问速度通常比物理内存慢,因为它需要将数据从磁盘加载到内存中,并且可能会因为磁盘访问速度慢而导致延迟
- 物理内存的访问速度通常比虚拟内存快,因为它是直接可用的内存资源,无需进行额外的磁盘访问
使用方式:
- 虚拟内存主要用于增加地址空间、提供内存管理和实现内存共享等功能,以提高系统的性能和稳定性
- 物理内存主要用于存储程序和数据,提供直接访问和使用的内存资源
- 应用层随便写个地址,内存是怎么检测出异常的
页面错误:当应用程序访问一个地址时,操作系统会检查地址是否犯法,并且是否位于应用程序的内存空间范围内,如果地址不合法或者越界,操作系统会触发一个页面错误异常。这个异常会被操作系统的异常处理机制捕获,操作系统会尝试回复应用程序的正常运行,通常是通过终止异常进程或发送信号给应用程序。
内存保护机制:操作系统会使用内存保护机制来保护系统内核空间和其他关键内存区域不被应用程序访问。如果应用程序尝试访问内核空间或其他受保护的内存区域,操作系统会检测到这种访问,并且触发一个异常。类似地,操作系统还会通过访问权限检查来防止应用程序访问不属于自己的内存区域。
地址空间隔离:在操作系统中,内核和用户空间通常会被隔离开,每个应用程序都有自己独立的地址空间。这种隔离可以防止应用程序直接访问内核空间,从而提高系统的安全性和稳定性。如果应用程序尝试访问内核空间,操作系统会检测到这种访问,并且触发一个异常。
访问权限检查:操作系统会根据内存页的访问权限设置来检查应用程序对地址的访问权限。如果应用程序尝试访问一个没有访问权限的地址,操作系统会检测到这种访问,并且触发一个异常。
- 引用层写的地址物理内存没分配,内核怎么操作的
异常处理:当应用程序访问尚未分配的物理内存时,CPU会检测到页面错误,并将控制权交给操作系统的异常处理程序;
页面分配:操作系统的异常处理程序会检查页面错误的原因,如果是因为访问了尚未分配的物理内存,则会分配相应的物理页面,并将该页面映射到应用程序的虚拟地址空间中;
数据传输:一旦物理页分配完成,操作系统会从磁盘或其他存储设备中读取设备,并将数据传输到新分配的物理页面中;
更新页表:操作系统会更新应用程序的页表,以将新分配的物理页面映射到应用程序的虚拟地址空间中。
恢复执行:一旦物理页面分配和数据传输完成,操作系统会将控制权返回给应用程序,并且重新执行导致页面错误的指令。这时,应用程序就可以正常访问新分配的物理页面了。
- 如果设备树随便写个错误字符串,内核驱动怎么处理的
驱动加载失败:如果设备树中包含错误的字符串或格式不正确,内核驱动可能无法解析设备树信息,导致驱动加载失败。这种情况下,内核可能会记录错误消息并不加载相关的驱动;
错误日志记录:内核通常会记录设备树解析过程中的错误信息到系统日志中,以便开发人员或系统管理员诊断问题。这些错误消息通常包括设备树节点路径、错误原因等信息,有助于快速定位问题;
警告信息:在某些情况下,内核驱动可能会尝试容错或部分解析设备树,但同时警告记录信息表明存在错误或不完整的设备树信息。这样可以在不影响系统正常运行的情况下提示用户存在的潜在问题。
忽略错误节点:内核驱动可能会尝试忽略设备树中存在错误的节点或属性,并继续解析其他正确的节点。这样可以尽可能多地利用正确的设备树信息,但也可能会导致某些设备功能无法正常工作;
恢复策略:在某些情况下,内核驱动可能会尝试通过一些恢复策略来尝试修复设备树中的错误,例如尝试从备份设备树中加载信息,或者尝试自动修复某些已知的常见错误。
参考资料
[1] Linux内核态内存泄漏检测工具–kmemleak工具原理及应用
[2] 案例分析(二)内存越界检测工具kasan