Linux系统Cannot allocate memory 报错处理详解

系统执行命令报错:fork:Cannot allocate memory
查看/var/log/messages
dbus[1489]: [system] Activating service name=‘org.freedesktop.problems’ (using servicehelper)
dbus[1489]: [system] Failed to activate service org.freedesktop.problems: Failed to fork (Cannot allocate memory)

可能原因:
1、内存不足或swap满了
2、进程数超限导致。
当系统内部的总进程数达到了pid_max时,再创建新进程时会报 fork:Cannot allocate memory错。

处理方案:
1、查看内存使用
查看内存使用情况:free -g 和 top
查看/var/log/message是否存在OOM的记录:grep “Out of memory” /var/log/messages
处理:
确定内存不足后,禁用内存占用较多的无关服务或者添加内存。

2、查看总进程数
核实总进程数是否超限,并修改总进程数 pid_max 配置。
查看系统pid_max值:sysctl kernel.pid_max (默认值为32768)
查看系统内部总进程数:pstree -p | wc -l
若总进程数达到了 pid_max,则系统在创建新进程时会报 fork Cannot allocate memory 错。
定位启动进程较多的程序:ps -efL
处理:
临时增加总进程数:sysctl -w kernel.pid_max=65535
永久修改总进程数,使配置立即生效:
echo “kernel.pid_max = 65535” >> /etc/sysctl.conf
sysctl -p

3、交换分区满
swap使用优先级:
Linux的swappiness参数用于控制虚拟内存swap的使用。
swappiness参数的默认值是60,也就是说当物理内存使用率达到40时,开始使用虚拟内存swap。
swappiness参数的值是0,则只有当物理机内存耗尽了以后才会使用虚拟内存swap。
swappiness参数的值是100,则立刻使用虚拟内存swap。

查看swap优先级:cat /proc/sys/vm/swappiness 或者 sysctl vm.swappiness
查看swap:swapon -s
开启swap:swapon -a
关闭swap:swapoff -a
重启swap:swapoff -a && swapon -a

处理:
swap优先级设置
临时设置:sysctl -p swappiness=0 或者 echo 0 > /proc/sys/vm/swappiness
永久设置:vi /etc/sysctl.conf 添加:vm.swappiness=0
sysctl -p

<think>我们正在讨论Linux的overcommit_memory设置。根据引用内容,这个参数控制内存分配的过度承诺策略。下面我将详细解释其作用、取值含义以及调整方法。 ### 一、overcommit_memory的作用 Linux内核在分配内存时采用了一种称为“Overcommit”(过度承诺)的策略,即允许程序申请超过实际物理内存加上交换空间(Swap)总量的内存。这种设计基于一个假设:并非所有程序都会完全使用它们申请的内存。`vm.overcommit_memory`参数就是用来控制这种策略的行为[^1][^2]。 ### 二、参数取值与含义 | 取值 | 含义 | 适用场景 | |------|------|----------| | **0** (默认) | 启发式过度承诺:内核根据当前空闲内存和请求内存量进行试探性分配。如果空闲内存不足,可能拒绝分配。 | 通用场景,但存在突发OOM风险[^1][^4] | | **1** | 总是过度承诺:内核总是允许内存申请,无论当前内存状态如何。 | 需要大量内存分配的科学计算或特殊应用[^2][^4] | | **2** | 禁止过度承诺:严格限制分配总量不超过`CommitLimit`(由物理内存×overcommit_ratio/100 + Swap计算得出)[^3]。 | 要求内存分配绝对可靠的生产环境[^1][^3] | ### 三、关键概念解释 - **CommitLimit**:系统允许分配的最大内存总量,计算公式为: $$ \text{CommitLimit} = \text{SwapSize} + \text{PhysicalMemory} \times \frac{\text{vm.overcommit\_ratio}}{100} $$ 仅在`vm.overcommit_memory=2`时生效[^3]。 - **Committed_AS**:当前系统已承诺(分配)的内存总量,可通过`grep -i commit /proc/meminfo`查看。 ### 四、配置方法 #### 1. 临时修改(重启失效) ```bash # 设置为严格模式(推荐生产环境) echo 2 > /proc/sys/vm/overcommit_memory # 调整过度承诺比率(默认为50) echo 80 > /proc/sys/vm/overcommit_ratio ``` #### 2. 永久修改 在`/etc/sysctl.conf`中添加: ```conf vm.overcommit_memory = 2 vm.overcommit_ratio = 80 ``` 生效配置: ```bash sysctl -p ``` ### 五、配置建议 | 场景 | 推荐配置 | 原因 | |------|----------|------| | **通用服务器** | `vm.overcommit_memory=0` | 平衡安全性与灵活性 | | **数据库/关键应用** | `vm.overcommit_memory=2` + `overcommit_ratio=70~90` | 避免突发OOM导致服务中断[^1][^3] | | **内存密集型计算** | `vm.overcommit_memory=1` | 确保大内存申请不被拒绝 | > ⚠️ **注意事项**: > - 当`vm.overcommit_memory=2`时,若程序申请内存超过`CommitLimit`,会立即返回`ENOMEM`错误(如Java报`Cannot allocate memory`) > - 使用`vm.overcommit_memory=1`时需确保Swap足够大,否则可能因极端内存耗尽导致系统崩溃 ### 六、配置验证 ```bash # 检查当前配置 sysctl vm.overcommit_memory vm.overcommit_ratio # 监控已承诺内存 watch -n 1 "grep -i commit /proc/meminfo" ``` 输出示例: ``` CommitLimit: 32458648 kB Committed_AS: 28014316 kB ``` --- ### 七、典型问题排查 #### 案例:MongoDB因ENOMEM启动失败 **现象**:日志报`mmap failed: Cannot allocate memory` **分析**: 1. 检查发现`vm.overcommit_memory=2`且`overcommit_ratio=50` 2. 计算`CommitLimit = 16GB物理内存×50% + 4GB Swap = 12GB` 3. MongoDB尝试mmap 18GB文件但被内核拒绝 **解决方案**: ```bash # 提高overcommit_ratio至90%(使CommitLimit=16×0.9+4=18.4GB) sysctl vm.overcommit_ratio=90 ``` --- §§ 相关问题 §§ 1. 如何计算`overcommit_ratio`的最佳值? 2. `vm.overcommit_memory=2`时,为什么Java应用仍可能触发OOM Killer? 3. 在Docker容器中如何有效控制内存过度承诺? 4. 如何通过`/proc/meminfo`预测OOM风险? 5. `vm.overcommit_memory`与cgroup内存限制的优先级关系?</think>### Linux `overcommit_memory` 详解与配置指南 #### 一、核心作用 `vm.overcommit_memory` 控制 Linux 内核的**内存分配策略**,决定是否允许应用程序申请超过物理内存 + Swap 的内存空间(即"过度承诺")。其设计基于一个关键观察:**大多数程序实际使用的内存远小于其申请量**[^1][^2]。 #### 二、参数取值与含义 | 取值 | 策略 | 内存分配规则 | 适用场景 | |------|------|--------------|----------| | **0** (默认) | 启发式过度承诺 | 内核根据公式 $ \text{空闲内存} \times \text{系数} + \text{Swap} $ 判断是否允许分配 | 通用服务器环境[^1][^4] | | **1** | 总是过度承诺 | 无条件允许所有内存申请 | 科学计算、HPC等特殊场景[^2] | | **2** | 禁止过度承诺 | 分配总量 ≤ $\text{Swap} + \text{物理内存} \times \frac{\text{overcommit\_ratio}}{100}$ | 关键生产系统[^3] | > ⚠️ **关键公式**(当`overcommit_memory=2`时): > $$ \text{CommitLimit} = \text{SwapSize} + \text{PhysicalMemory} \times \frac{\text{vm.overcommit\_ratio}}{100} $$ > 所有进程申请内存总和不得超过此值[^3]。 #### 三、配置方法 ##### 1. 临时修改(重启失效) ```bash # 设置为严格模式 echo 2 > /proc/sys/vm/overcommit_memory # 调整承诺比率(默认50%) echo 80 > /proc/sys/vm/overcommit_ratio ``` ##### 2. 永久配置 编辑 `/etc/sysctl.conf`: ```conf # 启用严格内存限制 vm.overcommit_memory = 2 # 允许使用80%物理内存+全部Swap vm.overcommit_ratio = 80 ``` 生效命令: ```bash sysctl -p ``` #### 四、配置建议 | 场景 | 推荐配置 | 原因 | |------|----------|------| | **通用服务器** | `vm.overcommit_memory=0` | 平衡安全性与灵活性 | | **数据库/关键应用** | `vm.overcommit_memory=2` + `overcommit_ratio=70~90` | 避免突发OOM[^1] | | **内存密集型计算** | `vm.overcommit_memory=1` | 确保大内存申请成功 | > 💡 **最佳实践**: > - 生产环境建议 `overcommit_memory=2` 配合 `overcommit_ratio=80` > - 监控 `/proc/meminfo` 中的 **Committed_AS**(已承诺内存)和 **CommitLimit**(最大承诺值) #### 五、配置验证 ```bash # 查看当前配置 sysctl vm.overcommit_memory vm.overcommit_ratio # 检查内存承诺状态 grep -i commit /proc/meminfo ``` 输出示例: ``` CommitLimit: 32458648 kB # 最大可承诺内存 Committed_AS: 28014316 kB # 当前已承诺内存 ``` #### 六、典型问题解决 **案例:MySQL 因 `ENOMEM` 启动失败** *原因*:`overcommit_memory=2` 且 `overcommit_ratio=50`,而物理内存16GB + Swap 4GB 时: $$ \text{CommitLimit} = 4\text{GB} + 16\text{GB} \times 0.5 = 12\text{GB} $$ 但MySQL尝试申请14GB内存。 *解决方案*: ```bash # 提高物理内存利用率至80% sysctl vm.overcommit_ratio=80 ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值