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

如何在Python中读取超出RAM容量的内存地址?

使用Python通过mmap读取/dev/mem中的非RAM物理地址

当然可以用Python实现!你遇到的问题本质是os.lseek+os.read的方式没法处理超出RAM范围的物理地址——因为内核会把这类地址判定为无效,但mmap就刚好能解决这个问题,和你用C写的memhack工具原理完全一致。

为什么原来的方法会报错?

/dev/mem虽然看起来像普通文件,但它是物理内存的镜像。当你用os.lseek定位到超过系统RAM容量的地址时,内核找不到对应的物理内存页,自然会返回无效地址错误。而你要访问的0xFED01004属于内存映射I/O(MMIO)地址,是硬件寄存器的映射,本来就不在RAM范围内,所以必须用mmap来直接映射这个地址区间到用户空间。

Python实现代码

下面是对应你需求的实现,核心就是用mmap模块完成物理地址到虚拟地址的映射:

import os
import mmap

def read_mmio_address(phys_addr, length):
    # 获取系统页大小(通常是4096字节)
    page_size = os.sysconf(os.sysconf_names['SC_PAGE_SIZE'])
    # 计算页起始地址(必须页对齐)
    page_start = phys_addr & ~(page_size - 1)
    # 计算目标地址在页内的偏移
    offset = phys_addr - page_start

    # 以读写模式打开/dev/mem(需要root权限)
    with os.open("/dev/mem", os.O_RDWR | os.O_SYNC) as fd:
        # 映射目标物理页到用户空间
        # MAP_SHARED表示和内核共享映射,PROT_READ表示只读权限(如果需要写可以加PROT_WRITE)
        with mmap.mmap(
            fd,
            page_size,
            mmap.PROT_READ,
            mmap.MAP_SHARED,
            offset=page_start
        ) as mem:
            # 读取指定长度的内容
            data = mem[offset:offset+length]
            return data

if __name__ == "__main__":
    # 目标物理地址0xFED01004(十进制4275048452),读取2字节
    target_addr = 0xFED01004
    result = read_mmio_address(target_addr, 2)
    print(f"读取到的数据: {result.hex()}")
    print("操作完成")

关键细节说明

  • 页对齐要求:mmap的offset参数必须是系统页大小的整数倍,所以我们需要先把目标地址向下对齐到最近的页起始地址,再通过偏移量定位到具体寄存器位置。
  • 权限问题:运行这个脚本必须使用root权限(比如sudo python3 your_script.py),因为/dev/mem是特权设备,普通用户没有访问权限。
  • 映射权限:如果需要写入寄存器,可以把mmap.PROT_READ改成mmap.PROT_READ | mmap.PROT_WRITE。
  • 资源释放:用with语句自动管理文件描述符和mmap对象,避免资源泄漏。

验证效果

这个方法不需要扩展RAM到4GB,直接就能访问MMIO地址,和你用C写的memhack工具效果完全一致。运行后就能读取到0xFED01004地址的2字节寄存器内容了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 08:52:31