构建说明
[TOC] art-pi 构建命令12345678910111213141516171819202122232425262728293031export CROSS_COMPILE=arm-none-eabi- ARCH=armmake stm32_defconfigmake menuconfig > General setup [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support > Device Drivers > Block devices [*] RAM block device support (1) Default number of RAM disks (2048) Default RAM disk size (kbytes) > System Type (0xC0000000) (S)DRAM Base Address (0x02000000) (...
linux_makefile
[TOC] 阅读技巧 使用make V=1来查看详细的编译过程 使用make -p来查看所有的变量和规则 顶层makefile判断GUN make 版本 检查当前的 Make 版本以确保满足条件 如果 output-sync 不在其中,这意味着当前使用的 GNU Make 版本低于 4.0,因此代码会触发一个错误,提示用户需要 GNU Make 4.0 或更高版本,并显示当前的 Make 版本 $(MAKE_VERSION)。 123ifeq ($(filter output-sync,$(.FEATURES)),)$(error GNU Make >= 4.0 is required. Your Make version is $(MAKE_VERSION))endif 检测内部变量是否被覆盖 检查 $(MAKECMDGOALS) 变量中是否包含以 __ 开头的目标。$(MAKECMDGOALS) 是一个特殊变量,包含了命令行中指定的所有目标。如果发现有以 __ 开头的目标,代码会触发一个错误,提示这些目标仅供内部使用。这种检查有助于防止用户意外调用内部目标,确保构...
init
[TOC] init/init_task.c 内核线程的一个核心特征是:它们没有自己独立的用户地址空间。它们只在内核空间运行,而内核地址空间是所有进程共享的。因此,内核线程不需要一个属于自己的内存描述符 struct mm_struct,所以它们的 task->mm 指针通常是 NULL init_task 就是大名鼎鼎的 PID 0 进程,也常被称为 swapper 进程。从它的标志位 .flags = PF_KTHREAD 可以看出,它是一个内核线程。 init_task 的调度策略(policy)是 SCHED_NORMAL,这意味着它是一个普通的分时调度任务,而不是实时任务。但是初始化阶段调用了init_idle(),使得它的sched_class 是 SCHED_IDLE,这样它就可以作为 CPU 的空闲任务运行。但是fork出来的其他进程继承的还是 SCHED_NORMAL 策略。 进程的“始祖”:init_task 是系统中所有进程的祖先。在系统启动后,它会创建第一个内核线程 kernel_init(它最终会成为 PID 1 的...
bio
[toc] include/linux/bio.hBIO 迭代器与数据段访问接口 (bio_iter, bio_advance_iter)核心功能该代码片段定义了一系列宏和static inline函数,它们共同构成了一个用于遍历和操作 struct bio(块 I/O 请求的基本单元)中数据段(bio_vec)的API。其核心功能是为块设备驱动提供一个标准、高效且安全的接口,用于: 访问当前数据段: 获取当前 I/O 进度(由 bio->bi_iter 迭代器所指向位置)的物理页、页内偏移和数据长度。 迭代遍历: 提供遍历 bio 中所有数据段的机制。 更新进度: 在驱动处理完一部分数据后,精确地更新 bio 的 bi_iter 迭代器,使其指向下一个待处理的数据位置。 状态查询: 提供辅助函数来查询 bio 的状态,例如数据方向(读/写)、是否包含有效数据等。 实现原理分析 迭代器设计模式: 这套 API 的核心设计思想是迭代器模式。struct bio 内部包含一个 struct bvec_iter bi_i...
blk-ioc
[toc] block/blk-ioc.c I/O上下文管理(I/O Context Management) 进程I/O优先级的关联与继承历史与背景这项技术是为了解决什么特定问题而诞生的?这项技术是为了解决在多任务操作系统中,如何区分和管理不同进程发起的I/O请求的重要性,从而实现更智能、更公平的I/O调度。 在blk-ioc.c(I/O Context)所代表的机制出现之前,内核的I/O调度器(I/O Scheduler)对所有进程发起的I/O请求几乎一视同仁。这会导致严重的问题: 优先级反转:一个高优先级的CPU密集型任务(如交互式桌面应用)可能会因为一个低优先级的后台I/O密集型任务(如文件索引、备份)而变得卡顿。后台任务产生的大量磁盘I/O请求会填满I/O队列,使得前台应用的关键数据读写请求需要等待很长时间。 资源争用不公:多个进程同时进行磁盘读写时,无法区分哪些进程的I/O应该被优先满足。例如,一个正在播放视频的媒体播放器和...
blk-mq
[toc] block/blk-mq.c 多队列块层核心(Multi-Queue Block Layer Core) 现代存储I/O性能的基石历史与背景这项技术是为了解决什么特定问题而诞生的?blk-mq(Block Multi-Queue)框架的诞生是为了从根本上重构Linux的块设备层,以适应现代存储硬件的飞速发展,特别是高速闪存设备(SSD、NVMe)的出现。 传统的Linux块层(single-queue block layer)是为机械硬盘(HDD)设计的,其核心是一个per-device的单一请求队列。这种设计在HDD时代是合理的,因为磁盘的机械寻道时间是主要瓶颈。然而,随着能够处理数十万甚至数百万IOPS(每秒I/O操作数)的闪存设备的普及,这个单一队列的设计成为了新的、严重的性能瓶颈: 锁争用:在多核CPU系统上,所有核心提交I/O时都必须争抢保护这个单一队列的全局锁。这种锁争用导致CPU无法有效扩展,即使硬件有能力处理更多请求,软件层面也无法将请求高效地提交给硬件。 缓存行弹跳:对单一队列的频繁访问导致其数据所在的...
block
[toc] Linux 源码中的 block 目录:块设备 I/O 的核心中枢block 目录是 Linux 内核 I/O 栈的心脏。它负责管理所有块设备(如硬盘驱动器 HDD、固态硬盘 SSD、U 盘等)的数据交换。这一层的主要目标是提供一个通用的、高效的框架,将上层文件系统和应用程序的 I/O 请求,转化为底层具体硬件驱动程序可以执行的操作。 一、 历史与背景这项技术是为了解决什么特定问题而诞生的? block 层的诞生是为了解决两个核心问题: 抽象与解耦:如果没有一个通用的块设备层,每个文件系统(如 ext4, XFS)都需要自己编写直接与各种硬盘驱动(SATA, SCSI, NVMe)对话的代码。这会导致代码冗余、开发复杂且难以维护。block 层提供了一个标准的接口,使得文件系统无需关心底层硬件的具体细节,反之亦然。 性能优化:对存储设备的随机访问通常效率很低,尤其是在机械硬盘上,会导致磁头频繁寻道,浪费大量时间。block 层通过引入 I/O 调度器 (I/O Scheduler),可以对传入的 I/...
genhd
[toc] block/genhd.c 通用硬盘驱动(Generic Hard Disk Driver) 内核中块设备的表示与管理历史与背景这项技术是为了解决什么特定问题而诞生的?这项技术是为了在Linux内核中创建一个统一的、抽象的块设备表示,以解决如何管理和表示各种各样的块存储设备(如硬盘、软盘、U盘、RAID卷等)的问题。 在genhd.c(Generic Hard Disk)所代表的框架出现之前,内核中对不同类型块设备的管理是零散和不一致的。genhd.c的诞生旨在解决以下核心问题: 设备抽象:需要一个通用的数据结构来描述一个块设备,无论它是物理硬盘、一个硬盘上的分区,还是一个由多个磁盘组成的逻辑卷。这个结构就是struct gendisk。 分区管理:一个物理磁盘通常被划分为多个分区。内核需要一个标准的机制来发现、解析和表示这些分区,并将每个分区也作为一个独立的块设备呈现给上层。genhd.c负责扫描分区表并为每个分区创建设备节点。 设备注册与命名:需要一个统一的机制来向内核注册新的块设备,并为其分配一个唯一的设备号(major/minor ...
amba
[TOC] drivers/amba: Linux的AMBA总线与SoC设备驱动核心drivers/amba 目录是 Linux 内核中用于管理和驱动基于 AMBA (Advanced Microcontroller Bus Architecture) 总线的外设的核心框架。在现代基于 ARM 的片上系统 (SoC) 中,几乎所有的片上外设(如 UART、GPIO、SPI、I2C、定时器等)都挂载在 AMBA 总线上。因此,这个目录是 ARM SoC 平台驱动程序的基石。 一、 历史与背景这项技术是为了解决什么特定问题而诞生的? 在嵌入式系统中,特别是 SoC 中,外设不是像 PCI 或 USB 设备那样可以在运行时动态发现的(即非“热插拔”或“可枚举”的)。它们是静态地集成在芯片上的,其物理地址和中断号在芯片设计时就已经固定。 早期的 Linux 内核通过在 C 代码(board-*.c 文件)中硬编码这些“平台设备”(platform devices)的信息来支持它们。这种方法导致了巨大的问题: 内核与硬件紧密耦合: 每支持一款新的开发板,就需要编写一个...
dma-buf
[TOC] drivers/dma-buf DMA-BUF (DMA Buffer Sharing) Framework 高效的零拷贝缓冲区共享框架历史与背景这项技术是为了解决什么特定问题而诞生的?这项技术以及其所在的dma-buf子系统,是为了解决现代异构计算系统中一个核心的性能和效率问题:如何在不同的硬件设备(驱动)之间高效地共享内存缓冲区,而无需进行昂贵的数据拷贝。 消除数据拷贝(Zero-Copy):在典型的多媒体处理流程中,一个数据流(如视频帧)可能需要经过多个硬件单元处理:例如,从摄像头控制器捕获,由视频编解码器(CODEC)进行编码/解码,交由GPU进行渲染或后期处理,最后发送到显示控制器进行显示。在没有dma-buf的时代,每一步之间的数据传递通常都需要CPU介入,将数据从一个设备的内存区域拷贝到另一个设备的内存区域,这会消耗大量的CPU周期和内存带宽,是系统性能的主要瓶颈。 统一的共享接口:在dma-buf出现之前,不同的子系统有各自私有的缓冲区共享方式(例如V4L2的USERPTR)。 这导致了接口不统一,无法实现任意设备间的缓冲...







