广东建设安全员报名网站,秦皇岛建设里二手房,比较好的网站建设品牌设计,科泉网站目录
三 内核的运行
9 设备树#xff1a; 1) 设备树产生缘由 2) 设备树方案的流程 3) 有了上述概念#xff0c;为了支撑整个设备树的工程实现#xff0c;内核实现以下内容 4) 内核解析设备树 5) 入口分析 6) 解析处理。
10 udev devfs sysfs
11 系统中的USB设备
12 网…目录
三 内核的运行
9 设备树 1) 设备树产生缘由 2) 设备树方案的流程 3) 有了上述概念为了支撑整个设备树的工程实现内核实现以下内容 4) 内核解析设备树 5) 入口分析 6) 解析处理。
10 udev devfs sysfs
11 系统中的USB设备
12 网络子系统
13 文件子系统
四 运行的内核 三 内核的运行
9 设备树 1) 设备树产生缘由 为解决板级设备杂乱的问题提供一种简洁方便的管理方案 通过定义一些规则按规则描述设备信息然后由内核解析动态生成设备相关代码完成设备的挂载 相对硬件编码而言规则可以看作是在代码上面又封装了一层更加灵活 而且规则可以定义的更适合人类阅读这样对提高效率和复用也很有帮助 2) 设备树方案的流程 定义设备数规则根节点子节点节点属性节点属性值cell单元引用等等。 需要注意根 需要注意可以支持c语言预处理 需要注意节点可以被覆盖重写 需要注意一些节点有限制比如CPU 节点中的size必须为0 memory的类型必须为memory 需要注意节点名称带有 根 标记 属性可以有值也可以无值 属性值可以为字符串字符串数组以及字节数组等形式 cell单元需要注意格式其地址和size由父节点决定 中断分ppi spi分上升沿下降沿等有专有定义 引用可以使用label形式也可以自定义全局唯一值来实现 兼容属性定义为从一般到特殊如果一致需要通过model属性区分 以上为设备树本身的一些构成规则编写和查看设备树文件时会用到上述内容。 从名称可以看出来设备树的组织结构形式为树。树是一种层次结构对应到设备上也代表着根、枝、叶的构成。 根可以看作是顶层总线下面挂接了CPU、内存和其他总线总线下面还可以有总线和设备这样一级一级展开构成了系统的硬件体系结构 对应到设备树中也就存在着父节点和子节点 3) 有了上述概念为了支撑整个设备树的工程实现内核实现以下内容 首先是设备树规则不再多说。 其次是设备树文件dts格式source文件另外还有dtsi格式属于头文件设备树支持头文件引用这有利于代码复用和管理。除此设备树还支持C语言的宏定义等 编写设备树文件后该文件内容是human readable的但不是计算机容易readable的所以还需要进行转换 内核提供dtc工具将dts文件内容编译成dtb格式。blob代表着二进制的对象。内核读取dtb格式内容动态生成内存中的设备对象。 dtc工具在内核源代码的/scripts/dtc/下编译内核源代码时会编译出主机端的dtc工具。需要打开内核的CONFIG_DTC选项配置其为Y 如果配置了CONFIG_ARM_APPENDED_DTBy编译内核源代码时会自动调用dtc工具编译生成dtb文件并将其附到内核尾部。 当然我们也可以单独执行该命令编译内核dtb文件比如 ./scripts/dtc/dtc -I dts -O dtb -o /home/nfsshare/hisi.dtb arch/arm/boot/dts/hi3519av100.dts 内核在编译过程中如何确定编译那些dts文件呢这些在makefile中会指定比如对于hisi来讲arch/arm/boot目录下makefile中有
include $(srctree)/arch/arm/boot/dts/Makefile在这个makefile中又会引入dtb-$(CONFIG_ARCH_HISI) \hi3519-demb.dtb 定义了dtb目标目录下有hi3519-demb.dts源文件这样dtc工具就会将该文件编译为目标的dtb文件 dtc工具不但可以编译dtb文件还可以将dtb文件反编译为dts文件。我们看到为了管理和复用代码dts文件支持头文件引用节点覆盖等。 当文件变得庞大时对于确认和查找节点的最终描述反而有点不方便此时可以使用反编译过程将dtb文件反编译为dts文件。 反编译后的文件是最终整理过的结果是一颗比较规整和标准的树结构节点描述是唯一的这对于确认节点的最终描述反倒是比较方便的。反编译命令如下 ./scripts/dtc/dtc -I dtb -O dts -o /home/nfsshare/hisi.dts arch/arm/boot/dts/hi3519av100-smp-flash.dtb 可以看到输入-I和输出-O格式发生了调换输出文件-o也变为了dts格式默认输入源倒是dtb 4) 内核解析设备树 有了dtb文件内核就可以解析该文件动态生成设备对象。 dtb文件的解析在内核启动过程的开始阶段最终也是解析为一棵树。待确认。后续在内核启动的后期阶段init线程中加载设备驱动时会遍历之前解析的树 找到每一个节点生成节点相关的设备对象及属性信息。待确认 到此整个链条就完整了。 5) 入口分析 除了内核uboot也是可以支持设备树的。相应的就有以下几种可能 A uboot支持设备树uboot解析设备树将解析后的结果地址告诉内核这种应该是不行的从软件开发感觉来讲也没必要反而增加了uboot和内核之间的耦合度 B uboot支持设备树uboot不解析设备数只是将dtb文件的地址告诉内核由内核解析从特定内存或者存储地址获取dtb信息并进行解析。 实际中是采用这种方式bootm启动内核时除了传递内核地址外还需要在命令行参数中增加dtb的地址。这种方式二者之间通过dtb达成一致。只要对dtb的解读一致即可。 其实也完全可以做到不存在任何耦合比如dtb文件只在内核这一端生成 C uboot不支持设备树这种情况下uboot仍然按照bootm启动内核设备树的相关操作完全由内核完成。 此时在内核编译中平台体系结构相关部分不再是obj-y的目标而是dtb-y。查看内核源代码可以发现此时arch/arm/目录下的mach-xxx目录下体系结构相关代码已经很少 转而在arch/arm/boot/dts目录下有大量体系结构相关的dts存在。 makefile中也是指定dtc工具编译dtb目标同时定义了zImage-dtb目标由原始vmlinux生成压缩的zImage后通过cat $(obj)/zImage $(DTB_OBJS_FULL) $将dtb目标缀在zImage后面生成zImage-dtb 最终生成uboot引导的uImage镜像也是基于zImage-dtb结果。 $(obj)/uImage: $(obj)/zImage-dtb FORCE 用二进制编辑工具打开此时的uImage可以在末尾看到可读的dts痕迹比如P/soc/amba/uart04540000等说明内核镜像中包括了dtb内容。 为了让内核启动时自动查找dtb并进行解析需要打开配置选项CONFIG_ARM_APPENDED_DTB。 当上述选项配置为Y时在compressed目录下的head.S汇编代码中可以看到有对设备树的处理 补充一点zImage作为压缩镜像其生成$(obj)/zImage: $(obj)/compressed/vmlinux FORCE依赖于compressed下的目标 head.S汇编代码会嵌入到内核启动代码中判断启动合法条件引导跳转到C代码在head.S中会发现如下一段代码 #ifdef CONFIG_ARM_APPENDED_DTB/** r0 delta* r2 BSS start* r3 BSS end* r4 final kernel address (possibly with LSB set)* r5 appended dtb size (still unknown)* r6 _edata* r7 architecture ID* r8 atags/device tree pointer* r9 size of decompressed image* r10 end of this image, including bss/stack/malloc space if non XIP* r11 GOT start* r12 GOT end* sp stack pointer** if there are device trees (dtb) appended to zImage, advance r10 so that the* dtb data will get relocated along with the kernel if necessary.*/ldr lr, [r6, #0]#ifndef __ARMEB__ldr r1, 0xedfe0dd0 sig is 0xd00dfeed big endian#elseldr r1, 0xd00dfeed#endifcmp lr, r1bne dtb_check_done not found从上面代码可以看出r6是内核正常的结尾处D0 0D FE ED是dtb的魔数当CONFIG_ARM_APPENDED_DTB选项被选中时 会将内核正常结尾处也就是附加dtb开头的内容加载到lr中同时根据大小端将dtb的魔数设置到寄存器r1中 接着判断二者是否相等如果不等说明未找到dtb否则说明内核自带了dtb 如果发现存在dtb append则在后续解压内核时避免对dtb部分造成影响最终调整dtb的相关指针以便内核启动时能够正确加载和解析dtb 6) 解析处理。 10 udev devfs sysfs 设备的发现与管理 内核启动时初始化相关资源包括进程、内存、中断、锁、设备模型、文件系统框架、用户空间交互通道等并完成设备树的解析 内核创建init进程在恰当时机执行initcall区域的函数指针进行driver setup 各个驱动模块的初始化在执行过程中会进行总线注册和设备匹配匹配分多种条件包括id table设备名称设备树兼容性属性等等。一般按照严格到宽松的条件进行匹配。 匹配成功后驱动的probe接口将被调用进行设备的初始化及设备所需中断和内存等资源的申请 之后设备一般在中断的驱动下开始正常工作包括上层触发数据发送中断触发数据接收上层触发各种控制操作等。 在Linux中一切设备均抽象为文件。内核驱动中可以申请设备号成功后在proc/devices中可以看到设备号使用情况 设备号申请分自动和手动两种自动方式由内核提供空闲设备号手动由驱动主动注册设备号手动方式可能存在设备号冲突情况 设备驱动申请设备号并注册后只是在上述目录下可以看到新增加的设备号而/dev目录下并没有实际产生设备节点 要在/dev目录下产生设备节点有多种方式一种是驱动中调用内核接口device_create注册时自动生成设备节点一种是通过sysfs系统在用户空间通过udev工具生成还可以调用mknod程序手动生成。 在内核驱动中自动创建设备节点存在一些缺点比如节点命名问题特定功能节点的创建问题。 所以一些节点可能在需要时由用户空间程序创建会提供方便。但是完全交给用户空间也存在问题。比如设备发现问题。在错过设备驱动加载时机后如何发现设备。 这里也牵涉一些关于内核职责的问题比如机制与策略的分离。 2.6之后的内核提供了sysfs系统用于管理总线、驱动、设备及它们之间的关系。udev工具就是基于sysfs进行设备管理的用户空间程序。 借助udev工具可以很好的解决设备命名问题也可以在设备发现和移除时很方便的执行定制化动作。 整个流程为 首先内核在初始化过程中会加载内置驱动完成设备的初始化和部分设备的创建。 init程序加载用户空间第一个程序并执行时会执行udevd后台例程。 udevd会使用/etc/udev/udev.conf文件配置自己 udevd会监听内核设备事件包括add remove change等 检测到事件后会按优先级匹配/etc/udev/rules.d/下面的规则文件规则文件是udevd启动时预置到其内存数据结构中的 udevd是否会监听/etc/udev/rules.d目录下的规则文件的变化实时更新规则。应该要这样否则需要重启udevd获取系统这不符合用户体验要求。 udevd会遍历所有预置的规则匹配后就执行相应的动作包括赋值、执行动作、获取特定动作的结果进行赋值或执行动作 动作的执行要放到单独的环境中如果是脚本的话要明确指定shell类型udevd会fork子进程处理动作。ps可能会看到多个udevd daemon进程。 规则文件编写原则可参考已有规则文件其中有关属性和预定义变量可以通过执行udevadm info -q all -n /dev/xxx -a的输出查看 设备的相关操作信息会被记录到一个数据库中udevadm就是读取数据库信息来展示设备相关信息的。 -a参数可以输出设备的整个加载链条比如从最顶层的总线到下一级总线到再下一级总线直到当前指定设备为止。 设备的组成结构是一个树形结构比如执行udevadm info -q all -n /dev/sdd -a输出sdd设备信息如下 looking at device /devices/platform/ahci.0/ata4/host3/target3:0:0/3:0:0:0/block/sdd:KERNELsddSUBSYSTEMblockDRIVERATTR{ro}0ATTR{size}7814037168ATTR{stat} 4597 46 37126 69300 10595 5825 2513672 73590 0 53330 142880ATTR{range}16ATTR{discard_alignment}0ATTR{events}ATTR{ext_range}256ATTR{events_poll_msecs}-1ATTR{alignment_offset}0ATTR{inflight} 0 0ATTR{removable}0ATTR{capability}50ATTR{events_async}looking at parent device /devices/platform/ahci.0/ata4/host3/target3:0:0/3:0:0:0:KERNELS3:0:0:0SUBSYSTEMSscsiDRIVERSsdATTRS{rev}CV11ATTRS{type}0ATTRS{scsi_level}6ATTRS{model}ST4000VX005-2LY1ATTRS{state}runningATTRS{queue_type}simpleATTRS{modalias}scsi:t-0x00ATTRS{iodone_cnt}0x4826ATTRS{iorequest_cnt}0x4844ATTRS{queue_ramp_up_period}120000ATTRS{timeout}30ATTRS{evt_media_change}0ATTRS{ioerr_cnt}0x0ATTRS{queue_depth}31ATTRS{vendor}ATA ATTRS{device_blocked}0ATTRS{iocounterbits}32looking at parent device /devices/platform/ahci.0/ata4/host3/target3:0:0:KERNELStarget3:0:0SUBSYSTEMSscsiDRIVERSlooking at parent device /devices/platform/ahci.0/ata4/host3:KERNELShost3SUBSYSTEMSscsiDRIVERSlooking at parent device /devices/platform/ahci.0/ata4:KERNELSata4SUBSYSTEMSDRIVERSlooking at parent device /devices/platform/ahci.0:KERNELSahci.0SUBSYSTEMSplatformDRIVERSahciATTRS{modalias}platform:ahcilooking at parent device /devices/platform:KERNELSplatformSUBSYSTEMSDRIVERS可以看到树根是platform中间控制器scsi最后是block 另外需要注意到父节点中名称和属性都带S本节点中不带S这一点在书写规则文件时也适用。即规则文件中如果是匹配父节点的属性则需要使用ATTRS。 规则文件中至少需要一个匹配和一个赋值匹配使用赋值使用赋值可以是重命名节点相关属性或者执行定制动作。 使用udev工具主要就是通过规则匹配来执行相关动作所以规则文件匹配很重要。但是事件的产生比如设备插拔等是需要一定条件的这对规则文件的验证带来了一些麻烦 能否模拟整个过程对规则进行快速验证调试呢如果可以做到这点那么对提高效率就非常有帮助了。 udevadm提供了多个选项可以帮助用户快速调试验证规则。 首先让目标设备正常加载进系统中 然后使用前面的udevadm info选项查看系统中的事件信息包括一些本地属性和父节点信息 利用上述信息编写初步的规则文件 使用命令udevadm test /sys/devices/platform/ahci.0/ata4/host3/target3:0:0/3:0:0:0/block/sdd模拟规则的匹配和执行过程 上述命令后面部分是具体设备信息该命令选项只是模拟过程不会真正执行 命令也会输出规则文件的解析优先级使用该命令可进行初步调试 下面进行正式的验证 首先我们可以启动udevadm monitor监控实时的事件信息为调试提供分析依据如下所示
udevadm monitor --propertymonitor will print the received events for:UDEV - the event which udev sends out after rule processingKERNEL - the kernel ueventKERNEL[1624468946.462053] add /devices/platform/ahci.0/ata4/host3/target3:0:0/3:0:0:0/block/sdd (block)UDEV_LOG3ACTIONaddDEVPATH/devices/platform/ahci.0/ata4/host3/target3:0:0/3:0:0:0/block/sddSUBSYSTEMblockDEVNAMEsddDEVTYPEdiskNPARTS3SEQNUM1416MAJOR8MINOR48UDEV [1624468946.474712] add /devices/platform/ahci.0/ata4/host3/target3:0:0/3:0:0:0/block/sdd (block)UDEV_LOG3ACTIONaddDEVPATH/devices/platform/ahci.0/ata4/host3/target3:0:0/3:0:0:0/block/sddSUBSYSTEMblockDEVNAME/dev/sddDEVTYPEdiskNPARTS3SEQNUM1416MAJOR8MINOR48monitor会输出内核的uevent事件和udev处理后输出的event 其次使用udevadm trigger触发事件比如对于上述硬盘加载可以用如下触发命令 udevadm trigger --actionadd --subsystem-matchblock --sysname-matchsdd udevadm trigger --actionadd --subsystem-matchblock --sysname-matchsd* trigger支持shell的通配符匹配只触发满足规则的节点的事件这一点需要注意比如对于上面的第一条规则monitor输出 KERNEL[1624533496.063615] add /devices/platform/ahci.0/ata4/host3/target3:0:0/3:0:0:0/block/sdd (block)KERNEL[1624533496.063753] add /devices/platform/ahci.0/ata4/host3/target3:0:0/3:0:0:0/block/sdd/sdd1 (block)KERNEL[1624533496.063840] add /devices/platform/ahci.0/ata4/host3/target3:0:0/3:0:0:0/block/sdd/sdd2 (block)KERNEL[1624533496.063919] add /devices/platform/ahci.0/ata4/host3/target3:0:0/3:0:0:0/block/sdd/sdd3 (block)对于上述第二条monitor输出 KERNEL[1624533496.063995] add /devices/platform/hiusb-ehci.0/usb1/1-1/1-1.4/1-1.4.1/1-1.4.1:1.0/host4/target4:0:0/4:0:0:0/block/sdb (block)KERNEL[1624533496.064080] add /devices/platform/hiusb-ehci.0/usb1/1-1/1-1.4/1-1.4.2/1-1.4.2:1.0/host5/target5:0:0/5:0:0:0/block/sda (block)KERNEL[1624533496.064181] add /devices/platform/hiusb-ehci.0/usb1/1-1/1-1.4/1-1.4.2/1-1.4.2:1.0/host5/target5:0:0/5:0:0:0/block/sda/sda1 (block)KERNEL[1624533496.064269] add /devices/platform/hiusb-ehci.0/usb1/1-1/1-1.4/1-1.4.3/1-1.4.3:1.0/host6/target6:0:0/6:0:0:0/block/sdc (block)UDEV [1624533496.081699] add /devices/platform/hiusb-ehci.0/usb1/1-1/1-1.4/1-1.4.1/1-1.4.1:1.0/host4/target4:0:0/4:0:0:0/block/sdb (block)UDEV [1624533496.082981] add /devices/platform/hiusb-ehci.0/usb1/1-1/1-1.4/1-1.4.3/1-1.4.3:1.0/host6/target6:0:0/6:0:0:0/block/sdc (block)UDEV [1624533496.083941] add /devices/platform/hiusb-ehci.0/usb1/1-1/1-1.4/1-1.4.2/1-1.4.2:1.0/host5/target5:0:0/5:0:0:0/block/sda (block)UDEV [1624533496.085070] add /devices/platform/ahci.0/ata4/host3/target3:0:0/3:0:0:0/block/sdd (block)UDEV [1624533496.103061] add /devices/platform/hiusb-ehci.0/usb1/1-1/1-1.4/1-1.4.2/1-1.4.2:1.0/host5/target5:0:0/5:0:0:0/block/sda/sda1 (block)UDEV [1624533496.107014] add /devices/platform/ahci.0/ata4/host3/target3:0:0/3:0:0:0/block/sdd/sdd3 (block)UDEV [1624533496.107077] add /devices/platform/ahci.0/ata4/host3/target3:0:0/3:0:0:0/block/sdd/sdd2 (block)UDEV [1624533496.112003] add /devices/platform/ahci.0/ata4/host3/target3:0:0/3:0:0:0/block/sdd/sdd1 (block)可见monitor输出为满足trigger条件的节点并未输出父节点或子节点 另外trigger可以匹配的选项也是比较多的可以支持attribute匹配如下 udevadm trigger --actionadd --subsystem-matchblock --attr-matchsize7814037168 使用上述命令时需要注意只输出符合条件的节点另外发现trigger不触发同时匹配父子节点的条件
udevadm trigger --actionadd --attr-matchmodelST4000VX005-2LY1 --attr-matchsize7814037168 这一点与上面所述的规则也是一致的 trigger触发事件后udev就会匹配规则文件然后执行动作通过观察monitor的输出检查动作的执行是否符合预期。 另外udevadm control可以修改udev后台例程的日志级别 实际设备上发现修改udev.conf文件将日志级别从err改为debug或info后系统启动不了加载根文件系统后不再进一步加载其他程序这一点待研究确认。 通过上述流程可以发现新接入的设备会由内核产生eventudev可以捕获该event 如果错过设备接入时机没有捕获事件可以通过trigger主动触发让内核将之前保存的事件再次通知到应用层同样可以匹配规则执行动作 所以结合sysfs和udev可以解决设备的重命名和挂载等处理需求 最后补充强调一下 这里的trigger本质上是让内核重新发出事件也就是说实际上事件已经错过了。 根文件系统加载后对于用户空间加载前即udev本身启动监控前内核驱动加载过程中已经识别和加载的设备如何进行配置就是依靠该命令 但是udev是在用户空间启动的所以udev启动后如果需要处理内核加载过程中的设备事件信息就需要重新触发。但此时该如何确定匹配条件呢 答案是直接执行udevadm trigger不加参数此时内核会将所有产生的事件全部上报由udev按需处理。 11 系统中的USB设备 执行lsusb命令输出如下内容 Bus 002 Device 001: ID 1d6b:0001 主机控制器 根HUBBus 001 Device 001: ID 1d6b:0002 主机控制器 根HUBBus 001 Device 002: ID 05e3:0610 USB HUBBus 001 Device 003: ID 05e3:0610 USB HUBBus 001 Device 004: ID 05e3:0610 USB HUBBus 001 Device 009: ID 1c9e:9b3c 龙尚模块Bus 001 Device 006: ID 0424:2240 USB读卡器Bus 001 Device 007: ID 0424:2240 USB读卡器Bus 001 Device 008: ID 0424:2240 USB读卡器Bus 001 Device 005: ID 0403:6011 USB转串口Bus 001 Device 010: ID 1c9e:9b3c 龙尚模块Bus 003 Device 001: ID 1d6b:0002 主机控制器 根HUBBus 003 Device 002: ID 0eef:0001 触摸屏Bus 004 Device 001: ID 1d6b:0003 主机控制器 根HUB从上面可以看出有四个总线每个总线上各有1个或多个设备 从CPU角度来看整体的USB树形结构如下图所示
CPU --ohci 根设备全速设备--usb2 [1d6b:0001] 主机USB控制器--ehci 根设备高速设备--usb1 [1d6b:0002] 主机USB控制器--1-1 [05e3:0610] USB HUB--1-1.1 [1c9e:9b3c] 龙尚模块--1-1.4 [05e3:0610] USB HUB--1-1.4.1 [0424:2240] 三个存储卡USB口读卡器--1-1.4.2 [0424:2240]--1-1.4.3 [0424:2240]--1-1.2 nop--1-1.3 nop--1-2 [05e3:0610] USB HUB--1-2.1 [0403:6011] USB转串口--1-2.1:1.0 转换的多个串口--1-2.1:1.1--1-2.1:1.2--1-2.1:1.3--1-2.2 [1c9e:9b3c] 龙尚模块--xhci 根设备USB3.0--usb3 [1d6b:0002] 主机USB控制器--touch [0eef:0001] 触摸屏--usb4 [1d6b:0003] 主机USB控制器--usb4 [1d6b:0003] 主机USB控制器CPU本身带了三个控制器分别支持全速2.0以及3.0的USB设备。 12 网络子系统 文件抽象特性在网络子系统表达能力不强。 不过仍然可以通过iNode将网络子系统中的资源和对象跟文件关联起来这对特定情况下的问题查找很有帮助。 区分路由策略和路由表 待补充。 13 文件子系统 关键几个数据结构 超级块 inode 目录 文件 等。 文件子系统有两个主要问题需要处理一个是高效的组织结构一个是一致性。 这里一致性是更加棘手的一个问题。文件系统主要通过两个手段来保证一致性一个是日志一个是写时复制。 除此还有其他一些原则包括读写、节点、速度、大小、压缩、缓存、备份、索引、均衡、随机等原则。 具体参见博客 7.5 文件系统_龙赤子的博客-CSDN博客 关于缓存多说一点。 页缓存与缓冲区缓存。文件子系统构建后优化的一大目标就是缓冲。我们知道机械硬盘的吞吐量跟CPU和内存的处理速度差异太大。 特别是近二三十年摩尔定律使得CPU处理性能不断翻翻但是机械硬盘的速度并没有太大的改进。为了匹配速度上的差异就需要缓存来解决。 在嵌入式领域很多时候使用flash作为数据断电保存的介质。相对机械动作电子芯片的处理速度有很大的提升但是跟CPU和内存相比仍然有很大差距所以缓存仍然是需要的。 最开始块设备缓冲更多针对直接操作物理设备块是单独的跟页缓冲更多是针对文件映射没有关系这样一来同一份数据在内核中就可能存在多份。 后来将二者整合到一起在底层都是基于页缓冲。按物理页操作也是内核擅长的。 实际中可能出现文件内容改变、损坏、丢失的情况。解决思路是 A 文件定期备份 B 分类管理比如对于不变文件保证只读属性减少出错可能 C 监测文件IO状态获取相关信息辅助问题分析 D 异常断电、关机的特殊处理 E 电磁隔离保护 F 专用模块负责文件读写管理。 四 运行的内核 1 可以把内核想象为一个大进程把自己想想成CPUCPU就是一些寄存器的集合加逻辑处理过程。 2 内存视图看内核Linux 的内存视图 参见博客 学内核之十六linux内存管理结构大蓝图_龙赤子的博客-CSDN博客 包括内存实体 任务结构 链条 地址空间 3 内核与应用层的交互途径 proc sys dev ioctl netlink unix socket 4 关于堆栈 堆栈分内核堆栈和应用堆栈 对于ARM来讲在内核配置unwind选项的情况下堆栈是通过解析unwind段来回溯的。 unwind段中记录了各个函数的入栈指令然后根据发生异常时的PC地址定位到具体的函数之后反推堆栈操作得到上一级的lr和fp地址 lr为调用函数的返回地址通过该寄存器内容可以知道调用者是那个函数 fp为堆栈指针通过该寄存器可以定位堆栈边界这样一级一级回溯即可获取调用栈信息。 关于内核调用栈的回溯在内核unwind.c代码中 对CPU和堆栈的关系理解可参见博主的文章 学内核之四关于内核与硬件的衔接_龙赤子的博客-CSDN博客 5 关于内核调试分析 perf 性能跟踪 大框架 ftrace 函数调用跟踪 ebpf 事件跟踪