You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中实现无缓冲磁盘读取?解决参数错误及缓冲区问题

Linux下使用O_DIRECT直接读取磁盘扇区的正确姿势

问题根源

Linux下使用O_DIRECT标志读取磁盘时,有三个严格的对齐要求,缺一不可:

  • 文件读取的偏移量必须对齐到磁盘扇区大小
  • 存储数据的缓冲区地址必须对齐到磁盘扇区大小
  • 读取的字节数必须是扇区大小的整数倍

你原代码中os.read()会自动创建内部缓冲区,这个缓冲区的地址无法保证满足对齐要求,因此触发Invalid argument错误。

解决方法:用ctypes直接调用系统read函数

os.read()不支持传入自定义缓冲区,所以需要借助ctypes直接调用Linux系统级的read函数,这样就能使用你预分配的对齐缓冲区。

完整实现代码

import os
import ctypes
from ctypes import cdll, c_int, c_size_t, c_void_p

# 动态获取磁盘扇区大小(避免硬编码,适配不同设备)
disk_path = "/dev/sdc"
with open(disk_path, "rb") as f:
    sector_size = os.fstat(f.fileno()).st_blksize

# 定义系统级read函数的参数和返回值类型
libc = cdll.LoadLibrary("libc.so.6")
libc.read.argtypes = [c_int, c_void_p, c_size_t]
libc.read.restype = ctypes.c_ssize_t

buffer_size = 4096
# 确保缓冲区大小是扇区大小的整数倍
assert buffer_size % sector_size == 0, "缓冲区大小必须是扇区大小的整数倍"

# 预分配对齐的缓冲区
raw_buffer = ctypes.create_string_buffer(buffer_size + sector_size)
buffer_addr = (ctypes.addressof(raw_buffer) + sector_size - 1) & ~(sector_size - 1)
aligned_buffer = ctypes.string_at(buffer_addr, buffer_size)

disk_fd = None
try:
    # 打开磁盘设备,启用O_DIRECT
    disk_fd = os.open(disk_path, os.O_RDONLY | os.O_DIRECT)
    # 定位到对齐的偏移量(需确保是扇区大小的整数倍)
    target_offset = 12345 * 4096
    assert target_offset % sector_size == 0, "偏移量必须对齐到扇区大小"
    os.lseek(disk_fd, target_offset, os.SEEK_SET)
    
    # 调用系统read函数读取数据到对齐缓冲区
    bytes_read = libc.read(disk_fd, buffer_addr, buffer_size)
    if bytes_read == -1:
        raise OSError(f"读取失败: {ctypes.get_errno()}")
    
    # 处理读取到的数据,aligned_buffer即为包含数据的bytes对象
    print(f"成功读取{bytes_read}字节数据")
    # 示例:打印前16字节的十六进制值
    print(aligned_buffer[:16].hex())

finally:
    if disk_fd is not None:
        os.close(disk_fd)

关键注意事项

  • 必须用sudo运行脚本,直接访问磁盘设备需要root权限
  • 不要硬编码扇区大小,通过os.fstat().st_blksize动态获取更可靠
  • 偏移量、缓冲区大小、缓冲区地址三者必须同时满足对齐要求,任一不满足都会触发错误
  • 若需要写入操作,逻辑完全一致,替换为调用libc.write即可

内容的提问来源于stack exchange,提问作者Marus Gradinaru

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 03:32:51