locks
[TOC] fs/locks.c 文件锁与租约(File Locks and Leases)历史与背景这项技术是为了解决什么特定问题而诞生的?fs/locks.c 中实现的文件锁机制是为了解决在多进程、多用户环境下并发访问同一文件时可能导致的数据竞争和文件损坏问题。当多个进程同时对一个文件进行读写时,如果没有协调机制,操作的交错执行可能会导致不可预期的结果(例如,经典的银行转账问题)。文件锁为希望协作的进程提供了一种标准化的互斥机制。 具体来说,它解决了以下问题: 数据一致性:确保一个进程在修改文件(或文件的一部分)时,其他进程不能同时修改,防止数据被破坏。 原子操作:允许进程以原子的方式执行一系列操作,例如读取文件、修改内容、再写回文件,而不会被其他进程干扰。 进程间同步:提供一种简单的同步原语,让进程可以等待其他进程完成对文件的操作后再继续执行。例如,一个进程可以等待另一个进程生成完一个报告文件后再去读取它。 它的发展经历了哪些重要的里程碑或版本迭代?Linux中的文件锁机制是逐步演化而来的,主要融合了两种不同的Unix传统: BSD锁 (flock):早期L...
ramfs
[TOC] fs/ramfs/inode.c 内存文件系统(RAM Filesystem) 完全基于页缓存的极简文件系统历史与背景这项技术是为了解决什么特定问题而诞生的?Ramfs(RAM Filesystem)的诞生是为了提供一个最简单、最快速的、完全基于内存的文件系统。它主要解决了以下几个问题: 极速的临时存储:在很多场景下,如编译过程中的临时文件、脚本运行时的中间数据等,需要一个读写速度极快的存储区域。将这些数据存放在磁盘上会带来不必要的I/O开销,而ramfs提供了一个直接在内存中进行文件操作的解决方案。 内核机制的简化与基础:ramfs的设计极其简单,它没有复杂的磁盘格式、没有日志、也没有各种文件系统特性。这使得它成为一个优秀的“教科书”范例,用于展示Linux虚拟文件系统(VFS)和页缓存(Page Cache)是如何协同工作的。更重要的是,它的简单性使其成为构建更复杂内存文件系统(如tmpfs)的理想基础。 早期启动环境:在系统启动的早期阶段(initramfs),内核需要一个文件系统来存放必要的工具和脚本,但此时真正的磁盘驱动可能尚...
sync
[toc] fs/sync.c 数据同步(Data Synchronization) VFS层缓存回写的核心控制历史与背景这项技术是为了解决什么特定问题而诞生的?fs/sync.c 及其实现的一系列系统调用(sync, fsync, fdatasync)是为了解决操作系统设计中一个最根本的矛盾:性能与数据持久性(Durability)之间的权衡。 性能需求:物理磁盘(无论是机械硬盘还是SSD)的读写速度远低于内存(RAM)。为了提高I/O性能,Linux内核引入了页缓存(Page Cache)。当应用程序写入文件时,数据通常只是被写入到内存中的页缓存,并被标记为“脏”(Dirty),然后系统调用会立即返回成功。这种异步写入或**写回缓存(Write-back Cache)**机制极大地提高了写入操作的响应速度。 数据持久性需求:仅将数据写入内存是不可靠的。如果此时系统突然断电或崩溃,所有存在于页缓存中但尚未写入磁盘的“脏”数据都将永久丢失。对于数据库、文件编辑器、事务日志等关键应用来说,这会导致数据损坏或丢失,是不可接受的。 fs/sync.c中的同步(S...
super
[TOC] fs/super.c 超级块管理(Superblock Management) VFS与具体文件系统的桥梁历史与背景这项技术是为了解决什么特定问题而诞生的?这项技术是为了解决操作系统中一个根本性的抽象问题:如何让内核以一种统一、标准化的方式来管理和操作各种各样、格式迥异的文件系统。 在fs/super.c所代表的VFS(虚拟文件系统)层出现之前,操作系统内核如果要支持一种新的文件系统(例如,从minix fs切换到ext2),可能需要对内核的大量代码进行修改。fs/super.c及其相关代码的诞生就是为了: 提供统一接口:为用户空间程序(如mount命令)和内核其他部分提供一个稳定的、与具体文件系统无关的接口。无论底层是ext4, XFS, Btrfs还是NFS,上层都使用同样的方式来挂载、卸载和获取文件系统信息。 解耦通用逻辑与特定实现:将所有文件系统都共有的逻辑(如管理挂载点列表、维护缓存、权限检查的通用部分)从特定文件系统的实现(如如何从磁盘块中读取inode、如何分配数据块)中分离出来。 实现文件系统的可插拔性:创建一个框架,使得添加一个新的文件系...
sysfs
[TOC] fs/sysfs/fs.c & dir.c 内核对象文件系统(Kernel Object Filesystem) 将内核对象层次结构导出到用户空间历史与背景这项技术是为了解决什么特定问题而诞生的?Sysfs(System Filesystem)的诞生是为了解决一个在早期Linux内核中日益严重的问题:/proc文件系统的混乱。 /proc的无序扩张:/proc文件系统最初设计用于提供关于系统中正在运行的进程的信息(即/proc/[pid]目录)。然而,由于其便利性,内核开发者开始将各种与进程无关的系统信息、硬件状态和可调参数也塞入/proc,导致其结构混乱、内容混杂,缺乏统一的逻辑。 缺乏结构化视图:/proc中的信息是平面的、零散的,无法清晰地反映出系统中设备、驱动和总线之间复杂的层次关系和连接关系。例如,你很难从/proc中直观地看出某个USB设备连接在哪条总线上,以及它正在使用哪个驱动程序。 Sysfs是作为统一设备模型(Unified Device Model),或称为kobject模型,的一部分而被创造出来的。它的核心目标是提...
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...
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...
atomic
[TOC] include/asm-generic/bitops/generic-non-atomic.h generic_test_bit 和 const_test_bit 是两个用于测试位图中某个位是否被设置的函数。它们的实现方式略有不同,主要体现在对 volatile 关键字的使用上。generic_test_bit 函数使用了 volatile 关键字,这意味着它会读取内存中的值,而不是使用寄存器中的缓存值。这对于多线程或中断上下文中的位操作非常重要,因为它确保了读取的是最新的值。const_test_bit 函数则不使用 volatile 关键字,这意味着它可以在编译时进行优化,适用于编译时常量的测试。两者的实现都使用了位操作来确定指定的位是否被设置。这里仅进行了读取操作,没有进行写入操作.所以不需要进行原子操作 generic_test_bit 这里具有volatile会在每次读取时都从内存中读取值,而不是进行优化 1234567891011121314/** * generic_test_bit - 确定是否设置了位 * @nr:要...
compiler
[toc] include/linux/build_bug.hstatic_assert 静态编译警告123456789101112131415161718/** * static_assert - 在构建时检查整数常量表达式 * * static_assert() 是 C11 _Static_assert的包装器,具有 * little 宏魔术使消息成为可选的(默认为 * 测试表达式的字符串化)。 * * 与 BUILD_BUG_ON() 相反,static_assert() 可以在 global * 范围,但要求表达式为整数常量 * 表达式(即,__builtin_constant_p() 是不够的 * true 表示 expr)。 * * 另请注意BUILD_BUG_ON,如果条件为 * true,而 static_assert() 如果表达式为 *假。 */#define static_assert(expr, ...) __static_assert(expr, ##__VA_ARGS__, #expr)#define __static_assert...
内存管理与访问
[toc] include/linux/cache.h: 提供与CPU缓存行对齐相关的宏,如 ____cacheline_aligned__cacheline_aligned 缓存行对齐 这个修饰符确保变量在内存中对齐到缓存行的边界上。缓存行对齐可以减少缓存行冲突,提高缓存命中率,从而提高系统性能。在多处理器系统中,缓存行对齐尤为重要,因为多个处理器可能同时访问相同的内存区域。通过对齐,可以减少缓存一致性协议带来的开销。 在多处理器系统中,缓存行对齐可以减少缓存一致性协议带来的开销,主要原因如下: 缓存一致性协议:在多处理器系统中,每个处理器都有自己的缓存,用于存储频繁访问的数据。为了确保所有处理器看到的数据是一致的,系统使用缓存一致性协议(如MESI协议)。当一个处理器修改了某个缓存行中的数据,其他处理器必须更新或失效其缓存中的相应数据。这种一致性维护会带来额外的开销。 缓存行对齐的好处 减少伪共享:伪共享(False Sharing)是指多个处理器访问同一个缓存行中的不同数据项,导致频繁的缓存一致性操作。通过缓存行对齐,可以确保每个处理器访问的数据项位...