C语言中Futex系统调用始终返回errno 14问题求助
解决futex调用返回EFAULT(无效地址)的问题
核心原因分析
EFAULT错误本质是内核无法访问你传入的futex地址,不管你用虚拟地址还是物理地址,内核只认当前进程地址空间里的有效虚拟地址,直接用物理地址肯定无效——物理地址是硬件层面的,内核不会直接处理用户传入的物理地址作为futex参数。
具体解决步骤
确保futex地址在当前进程的地址空间内有效
你要唤醒的目标进程的futex虚拟地址(0x7f9e696b3004)属于那个死锁进程的地址空间,你的唤醒进程和目标进程是独立的地址空间,直接用这个地址对唤醒进程来说是未映射的无效区域,内核自然返回EFAULT。正确的跨进程futex唤醒方式
- 用共享内存存放futex变量:要让两个进程能操作同一个futex,必须把futex变量放在共享内存中(比如用
mmap的MAP_SHARED标志,或者shmget/shmat创建的共享内存段)。这样两个进程的虚拟地址可能不同,但会映射到同一块物理内存,内核能正确关联到同一个futex。 - 传递当前进程的共享内存虚拟地址:在唤醒进程中,你需要用自己进程里对应共享内存的虚拟地址调用
FUTEX_WAKE,而非目标进程的虚拟地址。
- 用共享内存存放futex变量:要让两个进程能操作同一个futex,必须把futex变量放在共享内存中(比如用
验证地址有效性的方法
在唤醒进程中,可以用access系统调用先检查地址是否可访问:if (access((void*)your_futex_addr, F_OK) == -1) { perror("address not accessible"); }如果这个调用失败,说明地址在当前进程里确实无效,得先解决内存共享的问题。
禁止直接使用物理地址
内核的futex接口只接受用户空间的虚拟地址,物理地址对用户进程无意义,内核不会将其转换为有效虚拟地址,直接传物理地址必然报错。
补充说明
你之前测试中,死锁进程的futex地址是它自身地址空间的,唤醒进程没有映射这块内存,所以内核无法访问。必须让futex变量处于跨进程共享的内存区域,才能在不同进程中通过各自的虚拟地址操作同一个futex。
内容的提问来源于stack exchange,提问作者Jacob Quisenberry
相关产品推荐
相关产品推荐

