从2.6.15的内核开始,顶层目录下面有了一个叫做block的目录,内核目录结构变成了现在这个样子: localhost-1:/usr/src/linux-2.6.22.1 # ls COPYING Documentation MAINTAINERS README arch crypto fs init kernel mm scripts sound CREDITS Kbuild Makefile REPORTING-BUGS block drivers include ipc lib net security usr 进入block目录,用旁光看一下: localhost:/usr/src/linux-2.6.22.1/block # ls Kconfig Makefile blktrace.c deadline-iosched.c genhd.c ll_rw_blk.c scsi_ioctl.c Kconfig.iosched as-iosched.c cfq-iosched.c elevator.c ioctl.c noop-iosched.c ### Linux Block 层详解 #### 一、Block 层简介 在 Linux 内核发展过程中,Block 层作为存储子系统的重要组成部分,在处理磁盘读写请求方面扮演着至关重要的角色。从内核版本 2.6.15 开始,内核源代码的顶级目录下增加了一个名为“block”的子目录,这标志着 Block 层被正式引入到了 Linux 内核的核心架构中。 在 2.6.22.1 版本的内核中,我们可以通过以下命令查看 block 目录的存在: ``` localhost-1:/usr/src/linux-2.6.22.1 # ls ``` 执行该命令后,我们可以看到 block 目录与其他核心组件并列存在,如 arch、crypto、fs 等。接下来,进入 block 目录查看其内容: ``` localhost:/usr/src/linux-2.6.22.1/block # ls ``` 此时可以看到 block 目录下的主要文件,包括但不限于: - `Kconfig`: 配置选项文件,用于指定 Block 层的各种配置选项。 - `Makefile`: 编译脚本,用于编译 Block 层相关的模块。 - `blktrace.c`: 用于跟踪块设备上的 I/O 操作。 - `deadline-iosched.c`、`cfq-iosched.c`、`noop-iosched.c`: 这些文件分别实现了不同的 I/O 调度程序,用于管理 I/O 请求的优先级和调度策略。 - `genhd.c`: 通用硬盘驱动程序的实现,用于处理块设备的初始化等操作。 - `ll_rw_blk.c`: 低级别读写块函数,是 Block 层与底层设备交互的核心部分之一。 - `scsi_ioctl.c`: SCSI 设备的用户空间控制接口。 #### 二、Block 层内部结构分析 为了更深入地理解 Block 层的工作原理,我们需要进一步分析 block 目录下的关键文件。我们来看一下 Makefile 文件中的配置选项: ``` obj-$(CONFIG_BLOCK):=elevator.oll_rw_blk.oioctl.ogenhd.oscsi_ioctl.o obj-$(CONFIG_IOSCHED_NOOP)+=noop-iosched.o obj-$(CONFIG_IOSCHED_AS)+=as-iosched.o obj-$(CONFIG_IOSCHED_DEADLINE)+=deadline-iosched.o obj-$(CONFIG_IOSCHED_CFQ)+=cfq-iosched.o obj-$(CONFIG_BLK_DEV_IO_TRACE)+=blktrace.o ``` 这里通过 CONFIG_BLOCK 等宏来控制 Block 层各个组件是否被编译进内核。例如,CONFIG_IOSCHED_NOOP 代表 No-Op(无操作)I/O 调度程序的启用。 接下来,我们关注 genhd.c 文件中的关键函数 `subsys_initcall(genhd_device_init);`,该函数在内核启动时会被调用来初始化 Block 层设备。具体地,`genhd_device_init` 函数实现如下: ```c static int __init genhd_device_init(void) { int err; bdev_map = kobj_map_init(base_probe, &block_subsys_lock); blk_dev_init(); err = subsystem_register(&block_subsys); if (err < 0) printk(KERN_WARNING "%s: subsystem_register error: %d\n", __FUNCTION__, err); return err; } ``` 其中,`bdev_map` 的初始化通过 `kobj_map_init` 来完成,用于创建块设备映射表;`blk_dev_init` 是 Block 层设备初始化的核心函数,它会在 `genhd_device_init` 被调用时被执行。 继续分析 ll_rw_blk.c 文件中的 `blk_dev_init()` 函数: ```c int __init blk_dev_init(void) { int i; kblockd_workqueue = create_workqueue("kblockd"); // 更多初始化操作... } ``` 这个函数负责创建一个名为 “kblockd” 的工作队列,用于异步处理块设备相关的任务。 #### 三、Block 层的主要职责 Block 层的主要职责包括: 1. **I/O 调度**: 通过对不同 I/O 调度算法的支持,Block 层能够有效地管理磁盘的读写请求,从而提高系统的整体性能。 2. **错误处理**: Block 层提供了错误检测和恢复机制,确保数据的完整性和一致性。 3. **设备初始化**: Block 层负责初始化各种块设备,为上层应用程序提供统一的访问接口。 4. **性能优化**: 通过对 I/O 请求进行合并、排序等操作,Block 层可以显著提高磁盘 I/O 的效率。 #### 四、Block 层的关键概念 - **Block Device**: 块设备是一种允许按固定大小的数据块进行读写的设备,如硬盘、SSD 等。 - **I/O Scheduler**: I/O 调度器用于决定何时以及如何将 I/O 请求发送到磁盘,不同的调度器有不同的策略,如 CFQ、No-Op 和 Deadline。 - **Queue**: 在 Block 层中,每个设备都有一个与之关联的 I/O 请求队列,用于存储待处理的 I/O 请求。 - **Request**: I/O 请求是操作系统发送给块设备的具体操作指令,包括读取或写入数据。 Block 层是 Linux 内核中的一个重要组成部分,它不仅提供了对块设备的抽象封装,还通过高效的 I/O 调度机制和错误处理策略提高了系统的整体性能和可靠性。对于深入理解 Linux 内核及其存储子系统的开发者来说,掌握 Block 层的原理和实现细节是必不可少的。
- 粉丝: 1
- 资源: 25
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助