
int fd = open("test", O_RDWR | O_CREAT | O_DIRECT, 0644);static ssize_text4_file_write_iter(struct kiocb *iocb, struct iov_iter *from){struct inode *inode = file_inode(iocb->ki_filp);if (unlikely(ext4_forced_shutdown(inode->i_sb)))return -EIO;#ifdef CONFIG_FS_DAX/* DAX写入路径处理 */if (IS_DAX(inode))return ext4_dax_write_iter(iocb, from);#endif/* 直接I/O */if (iocb->ki_flags & IOCB_DIRECT)return ext4_dio_write_iter(iocb, from);else/* 缓冲I/O */return ext4_buffered_write_iter(iocb, from);}使用直接 I/O 必须满足三重对齐:
lseek()/ pread()/pwrite() 的文件起始偏移,必须是逻辑块大小整数倍。read()/write()/pread()/pwrite() 的数据长度,必须是逻辑块大小整数倍。
__iomap_dio_rw()->iomap_dio_iter()->iomap_dio_bio_iter()->iomap_dio_bio_iter(),iomap_dio_bio_iter 函数会进行三重对齐判断,判断语句为:
if ((pos | length) & (bdev_logical_block_size(iomap->bdev) - 1) || !bdev_iter_is_aligned(iomap->bdev, dio->submit.iter))return -EINVAL;pos:表示文件偏移。
length:表示读写长度。
bdev_logical_block_size-1:逻辑块大小掩码。
条件1:(pos | length) & (bdev_logical_block_size(iomap->bdev) - 1) 用于检查:文件偏移 pos 必须是逻辑块大小整数倍;数据长度 length 必须是逻辑块大小整数倍。 条件2:!bdev_iter_is_aligned(iomap->bdev, dio->submit.iter)) 用于检查内存地址必须是逻辑块大小整数倍,具体实现为:
staticinlinebool bdev_iter_is_aligned(struct block_device *bdev,struct iov_iter *iter){return iov_iter_is_aligned(iter, bdev_dma_alignment(bdev), // 参数2:DMA 对齐要求(511或4095) bdev_logical_block_size(bdev) - 1); // 参数3:逻辑块块大小掩码(511或4095)}bool iov_iter_is_aligned(conststruct iov_iter *i, unsigned addr_mask,unsigned len_mask){if (likely(iter_is_ubuf(i))) {// 检查 1:长度是否对齐(必须是 512/4K 整数倍)if (i->count & len_mask)returnfalse;// 检查 2:内存地址是否对齐,逻辑块大小整数倍if ((unsignedlong)(i->ubuf + i->iov_offset) & addr_mask)returnfalse;return true; } ......}#define _GNU_SOURCE#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<fcntl.h>#include<string.h>#define ALIGN_SIZE 512 // 对齐要求#define BUF_SIZE 4096 // 数据长度intmain(){constchar *test_str = "hello";void *buf = NULL;int ret = posix_memalign(&buf, ALIGN_SIZE, 2 * BUF_SIZE);if (ret != 0) { perror("posix_memalign failed");return-1; }memcpy(buf, test_str, strlen(test_str));int fd = open("./mytest.txt", O_RDWR | O_CREAT | O_DIRECT, 0644);if (fd < 0) { perror("open O_DIRECT failed");free(buf);return1; } ret = pwrite(fd, buf, BUF_SIZE, 0);if (ret < 0) { perror("pwrite failed");goto out; }printf("直接I/O写入成功:%ld 字节\n", ret);memset(buf, 0, BUF_SIZE); ret = pread(fd, buf, BUF_SIZE, 0);if (ret < 0) { perror("pread failed");goto out; }printf("直接I/O读取成功:%ld 字节\n", ret);printf("读取内容:%s\n", (char *)buf); fdatasync(fd);out: close(fd);free(buf);return0;}# gcc direct_io.c

autopsy / sleuthkit 取证工具

磁盘中已经有了 “hello” 字符串记录。
最后:
我的新书《图解Linux网络编程》发布了,我对Linux网络编程的应用开发技术以及内核源码进行了深入的研究,并以图解方式创作了《图解Linux网络编程》这本书,如果你想系统性地学习Linux网络编程,从底层原理到上层应用彻底通关Linux网络编程,欢迎入手我的新书。