【沃趣科技】漫游Linux块IO

本文介绍了Linux中块设备IO的生命周期,从用户态程序的write系统调用开始,经过虚拟文件系统(VFS)、buffer/cache、Direct IO,到通用块层、设备驱动和IO完成的全过程。探讨了如devtmpfs、ext4文件系统、bio请求、gendisk结构、调度器、软中断和硬中断等关键概念,旨在提供对数据库系统性能影响的深入理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

在计算机的世界里,我们可以将业务进行抽象简化为两种场景——计算密集型IO密集型。这两种场景下的表现,决定这一个计算机系统的能力。数据库作为一个典型的基础软件,它的所有业务逻辑同样可以抽象为这两种场景的混合。因此,一个数据库系统性能的强悍与否,往往跟操作系统和硬件提供的计算能力、IO能力紧密相关。

除了硬件本身的物理极限,操作系统在软件层面的处理以及提供的相关机制也尤为重要。因此,想要数据库发挥更加极限的性能,对操作系统内部相关机制和流程的理解就很重要。

本篇文章,我们就一起看下Linux中一个IO请求的生命周期。Linux发展到今天,其内部的IO子系统已经相当复杂。每个点展开都能自成一篇,所以本次仅是对块设备的写IO做一个快速的漫游,后续再对相关专题进行详细分解。
在这里插入图片描述


从用户态程序出发

首先需要明确的是,什么是块设备?我们知道IO设备可以分为字符设备和块设备,字符设备以字节流的方式访问数据,比如我们的键盘鼠标。而块设备则是以块为单位访问数据,并且支持随机访问,典型的块设备就是我们常见的机械硬盘和固态硬盘。

一个应用程序想将数据写入磁盘,它需要通过系统调用来完成:open打开文件 —> write写入文件 —> close关闭文件。

下面是write系统调用的定义,我们可以看到,应用程序只需要指定三个参数:

  1. 想要写入的文件
  2. 写入数据所在的内存地址
  3. 写入数据的长度
SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,
		size_t, count)
{
   
	struct fd f = fdget_pos(fd);
	ssize_t ret = -EBADF;

	if (f.file) {
   
		loff_t pos = file_pos_read(f.file);
		ret = vfs_write(f.file, buf, count, &pos);
		if (ret >= 0)
			file_pos_write(f.file, pos);
		fdput_pos(f);
	}

	return ret;
}

而剩下的工作就进入到内核中的虚拟文件系统(VFS)中进行处理。


虚拟文件系统(VFS)

在Linux中一切皆文件,它提供了虚拟文件系统vfs的机制,用来抽象各种资源,使应用程序无需关心底层细节,只需要通过open、read/write、close这几个通用接口便可以管理各种不同的资源。不同的文件系统通过实现各自的通用接口来满足不同的功能。

devtmpfs

挂载在/dev目录,devtmpfs中的文件代表各种设备。因此,对devtmpfs文件的读写操作,就是直接对相应设备的操作。

应用程序如果打开的是一个块设备文件,则说明它直接对一个块设备进行读写,调用块设备的write函数:

const struct file_operations def_blk_fops = {
   
	.open		= blkdev_open,
    ... ...
	.read		= do_sync_read,
	.write		= do_sync_write,
    ... ...
};
<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值