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 1
现有用户态 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 1
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。 |