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

为何MIPS32汇编中调用mmap会返回ENODEV错误?

问题描述

我一直在尝试实现Linux下MIPS32汇编的内存管理,编写了一段用mmap分配8字节内存的代码:

.text
.global main
main:
    addi $sp, $sp, -32
    add $a0, $zero, $zero
    addi $a1, $zero, 8
    addi $a2, $zero, 1
    addi $a3, $zero, 2
    sw $zero, 16($sp)
    sw $zero, 20($sp)
    addi $v0, $zero, 4090
    syscall
    lw $a0, ($v0)
    
    add $a0, $zero, $zero
    addi $v0, $zero, 4001
    syscall

用gdb运行时,系统调用始终返回0x13,对应我的系统中的ENODEV错误。根据mmap手册页,这个错误会在指定文件的底层文件系统不支持内存映射时触发。我设置的参数如下:

  • 第1个参数:void addr[.length] = NULL = 0
  • 第2个参数:size_t length = 8
  • 第3个参数:int prot = PROT_READ = 1
  • 第4个参数:int flags = MAP_PRIVATE = 2
  • 第5个参数(存在16($sp)处):int fd = 0
  • 第6个参数(存在20($sp)处):off_t offset = 0
问题原因与解决方法

问题核心在于你用了文件描述符0(标准输入)做mmap,但标准输入对应的终端设备不支持内存映射,因此触发ENODEV错误。

如果只是要分配匿名内存(无需映射到文件),需修改两处:

  1. 在flags参数中加入MAP_ANONYMOUS(值为0x20),即MAP_PRIVATE | MAP_ANONYMOUS,对应十进制数值34;
  2. 将文件描述符fd设为-1,而非0。

修改后的代码如下:

.text
.global main
main:
    addi $sp, $sp, -32
    add $a0, $zero, $zero       # addr = NULL
    addi $a1, $zero, 8          # length = 8
    addi $a2, $zero, 1          # prot = PROT_READ
    addi $a3, $zero, 34         # flags = MAP_PRIVATE | MAP_ANONYMOUS (2 + 32)
    addi $t0, $zero, -1
    sw $t0, 16($sp)             # fd = -1
    sw $zero, 20($sp)           # offset = 0
    addi $v0, $zero, 4090       # mmap系统调用号(MIPS32 Linux为4090)
    syscall
    
    # 检查返回值:若v0为MAP_FAILED(0xffffffff)则代表分配失败
    li $t0, 0xffffffff
    beq $v0, $t0, exit
    
    # 此处可对分配的内存进行操作,例如写入数据
    # sw $zero, ($v0)
    
exit:
    add $a0, $zero, $zero       # 退出状态码0
    addi $v0, $zero, 4001       # exit系统调用号
    syscall

额外说明:

  • MIPS32 Linux系统调用的参数规则:前4个参数用$a0-$a3传递,第5、6个参数需存入栈的$sp+16和$sp+20位置,你之前的栈位置处理是正确的;
  • 若确实需要映射文件,需确保打开的是普通磁盘文件(通过open系统调用获取合法fd),而非终端、管道这类不支持mmap的设备。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 22:15:02