shell命令
[TOC] 语法if 条件语句 if:用于执行一个命令并根据其退出状态码执行不同的操作。 $(if $(KBUILD_OUTPUT),, ...): 这是一个条件判断语句。(if ...) 函数的语法是 $(if condition, then-part, else-part)如果 condition 为真,则执行 then-part;否则,执行 else-part。 环境变量 shift 命令用于移动参数 shift 命令用于移动参数。它会将所有参数左移一个位置,即 $2 的值赋给 $1,$3 的值赋给 $2,以此类推。$1 的值会被丢弃,而 $0(脚本名称)不会受到影响。 local 命令用于声明局部变量${parameter+word} 用于检查变量是否已经定义 一种参数替换语法,用于检查变量是否已设置并根据结果返回不同的值。以下是对这种语法的详细解释: 1${parameter+word} 如果 parameter 已设置且不为空,则结果为 word。 如果 parameter 未设置或为空,则结果为空字符串。 标志$BASH 指向的 she...
构建说明
[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) 是一个特殊变量,包含了命令行中指定的所有目标。如果发现有以 __ 开头的目标,代码会触发一个错误,提示这些目标仅供内部使用。这种检查有助于防止用户意外调用内部目标,确保构...
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...
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/...
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无法有效扩展,即使硬件有能力处理更多请求,软件层面也无法将请求高效地提交给硬件。 缓存行弹跳:对单一队列的频繁访问导致其数据所在的...
bits
[toc] include/linux/bits.hBIT_WORD 位图的字数12345678//include/asm-generic/bitsperlong.h#ifdef CONFIG_64BIT#define BITS_PER_LONG 64#else#define BITS_PER_LONG 32#endif /* CONFIG_64BIT */#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) include/linux/bitmap.hbitmap_weight 位图的权重 用于计算位图(bitmap)中设置为 1 的位的数量(即权重) 1234567static __always_inlineunsigned int bitmap_weight(const unsigned long *src, unsigned int nbits){ if (small_const_nbits(nbits)) return hweight_long(*src & BITMAP...
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 ...
hashtable
[TOC] include/linux/hashtable.hDEFINE_HASHTABLE 定义哈希表123#define DEFINE_HASHTABLE(name, bits) \ struct hlist_head name[1 << (bits)] = \ { [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT } hlist_for_each_entry 遍历哈希表12345678910111213141516171819202122232425262728293031323334#define hlist_entry(ptr, type, member) container_of(ptr,type,member)#define hlist_for_each(pos, head) \ for (pos = (head)->first; pos ; pos = pos->next)#define hlist_for_each_sa...







