
malloc 内存用于存放 TCP 连接收到的数据,在接收完成后,free 内存,结果在 top 和 free -m 指令的显示下,进程的内存并没有减少,反而随着连接的增加一直增加,free 的内存不会归还给 OS 吗?
1 wwqgtxx 2017-11-24 10:37:31 +08:00 via iPhone 取决于 glibc 或者是其他 malloc 提供者的实现 |
2 debuggerx 2017-11-24 10:55:35 +08:00 一般是 glibc 会复用 free 的内存,以尽量减少内存碎片的产生。。如果 free 一点就还给 os 一点内存很快就没法用了 |
3 seaswalker 2017-11-24 11:00:31 +08:00 malloc 这种分配器实现应该会维护一个分配链表,free 之后会将内存重新置为可分配状态,应该不会还给 OS,我觉得 |
4 VYSE 2017-11-24 11:01:48 +08:00 现有用户态 malloc 实现通常会向 kernel 申请一段内存自己优化管理,释放后会带来空隙,也就是碎片化 当然空隙以后被填上,开销比每次申请小很多 |
5 momocraft 2017-11-24 11:10:37 +08:00 不应该永远不还 很可能不立即还 |
7 facetest 2017-11-24 11:17:30 +08:00 via Android 一般不会,这样做效率太低 |
8 hxndg 2017-11-24 11:22:47 +08:00 我记得当年我还就这个问题写过一篇博客...下面这个是我当时搜到的资料,你可以看看. https://www.ibm.com/developerworks/linux/library/l-memory/ |
9 lijiangming 2017-11-24 11:23:28 +08:00 看到这个问题,立马取找出源码看了有一会了,glibc\malloc\malloc.c,里面有引用 arena.h,恰好之前也在 cii 中看到过 arena 得实现,好像是有维护一个已释放的内存链表,好像这是为了避免在相同进程中使用同一内存地址,细看还得花时间^o^ |
10 jiang1234321 OP @debuggerx 64*1024 个字节呢,不少吧 |
11 jiang1234321 OP @momocraft 没有新的连接建立的时候,内存也一直都没有释放,一直都不变 |
12 jiang1234321 OP @lijiangming 也就是说内存已经释放了,但是 OS 不会再一次分配给这个进程? |
13 jiang1234321 OP @hxndg 方便贴出来博客的连接吗?一大段英文 get 不到重点 |
14 jiang1234321 OP @wwqgtxx linux 平台的实现应该都是一样的吧 |
15 debuggerx 2017-11-24 12:34:32 +08:00 |
16 lijiangming 2017-11-24 14:01:42 +08:00 @jiang1234321 好像我说的记得有点问题,应该 arena 就是内存池,会返回重复得内存地址,我测试 int *a = (double *)malloc(sizeof(double)); free(a); int *b = (double *)malloc(sizeof(double)); free(b); 在 ubuntu16.4 64 位下测试结果 a 和 b 指向相同地址 |
17 lijiangming 2017-11-24 14:02:27 +08:00 @jiang1234321 复制错了,sizeof(int); 你可以测试一下 |
18 hxndg 2017-11-24 14:04:22 +08:00 |
19 owenliang 2017-11-24 14:29:52 +08:00 buffered/cached |
20 3dwelcome 2017-11-24 15:53:54 +08:00 free 会归还的。 往大的看,linux 把空余的内存都利用起来了,所以一般是检测 swap 占用率,来确定当前内存的用量。 往小的看,你可以尝试查看 cat /proc/[id]/status,里面有 vmpeak(进程启动后内存的最大占用量)和 vmsize(当前内存占用大小) 或者你技术更好,就用 /proc/[id]/maps 自己算页面大小,看看 malloc 究竟占了你多少空间。 |
21 3dwelcome 2017-11-24 16:14:28 +08:00 关于 top 里 virt 和 res 区别,想说几句。理解这个才能更好的测试数据。 前者是分配的内存,也就是 new/malloc 了多少,比如说 malloc 了 500M,那 virt 就是 500M. 后者是分配后,你实际使用的内存。比如 malloc 了 500M,但你代码里,只访问的前 50M 数据,那操作系统会很聪明的,只在物理内存里划分 50M 给你,剩下的就不占物理内存了,因为这部分你暂时没用到啊。所以 res 是 50M。 如果是有内存回收机制的,看 vmpeak/vmsize 也许不行,但纯 C++写的代码,是可以这样看的。 |
22 jiang1234321 OP @3dwelcome 多谢指导,再问一下,我启动程序的时候 top 看内存的时候 VIRT 直接到了 1523M,但是 RES 只有 15M,%MEM 也只有%0.8,这是什么原因? |
23 jiang1234321 OP |
24 datocp 2017-11-25 07:43:57 +08:00 via Android 当年在 ddwrt 只有 ralink 的设备通过 echo drop_cache 使这个 32M 内存的 dlink600 具备无限回复内存的能力。而同样版本针对 tplink wa701 的只会越用越少,所以针对这种设备直接每天定时重启,因为过低的内存至少已知会导致 dnsmasq 崩溃。 |
25 wanderer 2017-11-26 01:17:26 +08:00 madvise() |
26 a32b88z 2017-11-27 22:11:19 +08:00 这种问题,还是不要探究的好。 计算机专业的操作系统专业书可以看看了解下原理,至于你真的要完全搞明白 Linux 和其他 OS 是怎样管理内存的,没这必要,也不是普通人随随便便就能搞明白的。就算搞明白了对你也没什么用。 你只要知道操作系统自己会「智能」管理内存就行了。如果你自己开发程序,特别是 c、c++之类的,特别注意不要 leak 内存就 ok. 如果是 linux 系统管理,把重点放在观察 ps 命令里面那个 rss。 |