news 2026/7/2 2:56:44

一个由进程内存布局异常引起的问题

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
一个由进程内存布局异常引起的问题

前段时间业务反映某类服务器上更新了 bash 之后,ssh 连上去偶发登陆失败,客户端吐出错误信息如下所示:


图 - 0

该版本 bash 为部门这边所定制,但是实现上与原生版并没有不同,那么这些错误从哪里来?

是 bash 的锅吗

从上面的错误信息可以猜测,异常是 bash 在启动过程中分配内存失败所导致,看起来像是某些情况下该进程错误地进行了大量内存分配,最后导致内存不足,要确认这个事情比较简单,动态内存分配到系统调用这一层上主要就两种方式: brk() 和 mmap(), 所以只要统计一下这两者的调用就可以大概估算出是否有大内存分配了。

bash 是由 sshd 启动的,于是 strace 跟踪了一下 sshd 进程,结果发现异常发生时,bash 分配的内存非常地少,少到有时甚至只有几十字节也会失败,几乎可以断定 bash 在内存使用上没有异常,但在这期间发现一个诡异的现象,Bash 一直只用 brk 在分配小内存,brk() 失败后就直接退出了,一般程序使用的 libc 中的 malloc (或其它类似的 malloc) 会结合 brk 和 mmap 一起使用【0】,不至于 brk 一失败就分配不到内存,顺手查看了下 bash 的源码,发现它确实基于 brk 做了自己的内存管理,并没有使用 malloc 或 mmap。

但那并不是重点,重点是即使是只使用 brk,也不至于只能分配几十字节的内存。

进程的内存布局

进程的内存布局在结构上是有规律的,具体来说对于 linux 系统上的进程,其内存空间一般可以粗略地分为以下几大段【1】,从高内存到低内存排列:
1、内核态内存空间,其大小一般比较固定(可以编译时调整),但 32 位系统和 64 位系统的值不一样。
2、用户态的堆栈,大小不固定,可以用 ulimit -s 进行调整,默认一般为 8M,从高地址向低地址增长。
3、mmap 区域,进程茫茫内存空间里的主要部分,既可以从高地址到低地址延伸(所谓 flexible layout),也可以从低到高延伸(所谓 legacy layout),看进程具体情况【2】【3】。
4、brk 区域,紧邻数据段(甚至贴着),从低位向高位伸展,但它的大小主要取决于 mmap 如何增长,一般来说,即使是 32 位的进程以传统方式延伸,也有差不多 1 GB 的空间(准确地说是 TASK_SIZE/3 - 代码段数据段,参看 arch/x86/include/asm/processor.h 里宏 TASK_UNMAPPED_BASE 的定义)【4】
5、数据段,主要是进程里初始化和未初始化的全局数据总和,当然还有编译器生成一些辅助数据结构等等),大小取决于具体进程,其位置紧贴着代码段。
6、代码段,主要是进程的指令,包括用户代码和编译器生成的辅助代码,其大小取决于具体程序,但起始位置根据 32 位还是 64 位一般固定(-fPIC, -fPIE等除外【5】)。

以上各段(除了代码段数据段)其起始位置根据系统是否起用 randomize_va_space 一般稍有变化,各段之间因此可能有随机大小的间隔,千言万语不如一幅图:


图 - 1

所以现在的问题归结为:为什么目标进程的 brk 的区域突然那么小了,先检查一下 bash 的内存布局:


图 - 2

这个进程的内存布局和一般理解上有很大出入,从上往下是低内存到高内存:
#1处为进程的代码段和数据段,这两个区域一般处于进程内存空间的最低处,但现在在更低处明显有动态库被映射了进来。
#2处为 brk 的区域,该区域还算紧临着数据段,但是,brk 与代码段之间也被插入了动态库,而且更要命的是,brk 区域向高处伸展的方向上,动态库映射的区域贴的很近,导致 brk 的区域事实上只有很小一个空间(0x886000 - 0x7ac000)。

这并不是我们想要的内存布局,我们想要的应该是长成下面这样的:


图 - 3

看出来不同了没有,两个 bash 进程都是 64 位的,不同在于前者是 sshd 起的进程后者是我手动在终端上起起来的,手动 cat /proc/self/maps 看了下 64 位的 cat 的进程的内存布局也是正常的:


图 - 4

那 sshd 进程呢?

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/2 2:55:38

贵阳婚纱照拍的最好的是哪一家?

说实话,在贵阳备婚这件事里,“拍婚纱照是最容易让人纠结的一步”。 我当时的状态很典型: 一边刷到各种“3999全包”“零隐形消费”的套餐,一边又看到身边朋友吐槽“拍完加钱、修图加钱、服装还分档次”。 更现实的是—— 你以为选…

作者头像 李华
网站建设 2026/7/2 2:52:57

容器资源限制与配额管理实践

容器资源限制与配额管理实践随着容器化技术的普及,尤其是以Docker和Kubernetes为代表的平台成为云原生应用的基石,如何高效、安全地管理容器资源,确保应用性能与稳定性,同时提升基础设施利用率,已成为运维与开发团队面…

作者头像 李华
网站建设 2026/7/2 2:52:51

Rust语言基础开发教程

Rust语言基础开发教程:构建安全高效的系统级应用引言:为什么选择Rust?在当今的编程语言生态中,Rust以其独特的内存安全保证、卓越的性能表现和出色的并发处理能力脱颖而出。作为一门系统级编程语言,Rust不仅提供了C/C级…

作者头像 李华
网站建设 2026/7/2 2:49:50

Vue路由配置完整教程

Vue路由配置完整教程:构建单页面应用的导航核心引言:为什么需要Vue路由?在现代Web开发中,单页面应用(SPA)已成为主流架构。与传统多页面应用不同,SPA通过动态重写当前页面来与用户交互&#xff…

作者头像 李华
网站建设 2026/7/2 2:49:40

Go语言并发模式之WorkerPool设计实践

Go语言并发模式之WorkerPool设计实践在并发编程领域,Go语言以其轻量级的goroutine和高效的并发原语而著称。然而,无限制地创建goroutine可能导致资源耗尽和性能下降。WorkerPool(工作池)模式正是为了解决这一问题而生的经典并发模…

作者头像 李华
网站建设 2026/7/2 2:49:19

遗留系统与数据缺口制约香港企业财资中心发展

数据碎片化与系统整合薄弱正在阻碍亚洲财资转型进程。根据一份金融科技报告,香港需要持续投入金融科技基础设施建设、完善监管框架并加大人才培育力度,以巩固其作为亚洲企业财资管理中心的地位。该报告由香港金融科技协会(FTAHK)与…

作者头像 李华