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

Python中fork时提示无法分配内存,但服务器内存充足

解决线程中重复fork出现Errno 12内存不足的问题

这种情况我之前排查过类似的,虽然你已经排除了僵尸进程和物理内存不足的问题,但还有几个容易被忽略的关键点可能导致这个错误,咱们一步步分析:

1. 用户进程数上限被耗尽

系统默认会给每个用户设置最大进程数限制(RLIMIT_NPROC),哪怕物理内存还有剩余,只要进程数达到上限,就会报内存不足的错误。

你可以先在服务器上执行这个命令查看当前限制:

ulimit -u

再用这个命令统计当前用户已创建的进程数:

ps -u $(whoami) | wc -l

如果已用进程数接近上限,要么联系管理员调高限制,要么在代码里用resource模块动态调整(需要对应权限):

import resource

# 查看当前进程数的软/硬限制
soft_limit, hard_limit = resource.getrlimit(resource.RLIMIT_NPROC)
print(f"进程数限制: 软限制{soft_limit}, 硬限制{hard_limit}")

# 临时调高软限制(硬限制需要root权限才能修改)
resource.setrlimit(resource.RLIMIT_NPROC, (soft_limit + 50, hard_limit))

2. 线程中fork的兼容性隐患

这是最容易踩坑的点:在多线程环境下调用fork()本身就不安全!

fork只会复制当前调用fork的线程,其他线程的状态不会被复制。如果其他线程当时持有锁(比如Python的GIL、文件锁或者自定义锁),fork后的子进程里这些锁会处于永久锁定状态,导致资源泄漏、内存无法释放,后续再fork时就会出现异常。

解决思路:

  • 尽量不在线程中执行fork,把进程创建逻辑移到主线程中;
  • 如果必须在线程里fork,那fork后要立即调用exec系列函数(比如os.execvp)替换子进程的地址空间,避免继承父线程的不良状态;
  • 更稳妥的方式是用Python的multiprocessing模块创建子进程,它内部已经处理了多线程下fork的安全问题,比手动调用os.fork可靠得多。

3. 虚拟内存或地址空间耗尽

64位系统虽然虚拟地址空间很大,但如果每个子进程占用大量地址空间(比如打开了很多文件、加载了大库),累积起来也可能耗尽虚拟内存。你可以用以下命令排查:

# 查看虚拟内存和swap使用情况
free -h
# 查看内存状态和碎片情况
vmstat

另外要确保子进程退出时彻底释放了所有资源:关闭文件句柄、断开网络连接、清理临时数据等,这些资源残留会占用地址空间,导致后续分配失败。

4. 内存碎片问题

即使总内存充足,内存碎片过多也可能导致无法分配连续的内存块给新进程。这种情况可以尝试临时整理内存(需要root权限):

echo 1 > /proc/sys/vm/compact_memory

不过这只是临时方案,长远来看要优化子进程的内存使用,减少不必要的内存分配。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:19:09