free 内存的时候,内存是否会还给 OS 重新分配? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
jiang1234321
V2EX    Linux

free 内存的时候,内存是否会还给 OS 重新分配?

  •  
  •   jiang1234321
    jiangbo9510 2017-11-24 10:35:19 +08:00 5760 次点击
    这是一个创建于 2954 天前的主题,其中的信息可能已经有所发展或是发生改变。

    malloc 内存用于存放 TCP 连接收到的数据,在接收完成后,free 内存,结果在 top 和 free -m 指令的显示下,进程的内存并没有减少,反而随着连接的增加一直增加,free 的内存不会归还给 OS 吗?

    26 条回复    2017-11-27 22:11:19 +08:00
    wwqgtxx
        1
    wwqgtxx  
       2017-11-24 10:37:31 +08:00 via iPhone
    取决于 glibc 或者是其他 malloc 提供者的实现
    debuggerx
        2
    debuggerx  
       2017-11-24 10:55:35 +08:00
    一般是 glibc 会复用 free 的内存,以尽量减少内存碎片的产生。。如果 free 一点就还给 os 一点内存很快就没法用了
    seaswalker
        3
    seaswalker  
       2017-11-24 11:00:31 +08:00
    malloc 这种分配器实现应该会维护一个分配链表,free 之后会将内存重新置为可分配状态,应该不会还给 OS,我觉得
    VYSE
        4
    VYSE  
       2017-11-24 11:01:48 +08:00   1
    现有用户态 malloc 实现通常会向 kernel 申请一段内存自己优化管理,释放后会带来空隙,也就是碎片化
    当然空隙以后被填上,开销比每次申请小很多
    momocraft
        5
    momocraft  
       2017-11-24 11:10:37 +08:00
    不应该永远不还 很可能不立即还
    noli
        6
    noli  
       2017-11-24 11:17:21 +08:00 via iPhone
    @momocraft 这个描述最简洁。
    facetest
        7
    facetest  
       2017-11-24 11:17:30 +08:00 via Android
    一般不会,这样做效率太低
    hxndg
        8
    hxndg  
       2017-11-24 11:22:47 +08:00
    我记得当年我还就这个问题写过一篇博客...下面这个是我当时搜到的资料,你可以看看.
    https://www.ibm.com/developerworks/linux/library/l-memory/
    lijiangming
        9
    lijiangming  
       2017-11-24 11:23:28 +08:00
    看到这个问题,立马取找出源码看了有一会了,glibc\malloc\malloc.c,里面有引用 arena.h,恰好之前也在 cii 中看到过 arena 得实现,好像是有维护一个已释放的内存链表,好像这是为了避免在相同进程中使用同一内存地址,细看还得花时间^o^
    jiang1234321
        10
    jiang1234321  
    OP
       2017-11-24 12:26:39 +08:00
    @debuggerx 64*1024 个字节呢,不少吧
    jiang1234321
        11
    jiang1234321  
    OP
       2017-11-24 12:27:21 +08:00
    @momocraft 没有新的连接建立的时候,内存也一直都没有释放,一直都不变
    jiang1234321
        12
    jiang1234321  
    OP
       2017-11-24 12:28:51 +08:00
    @lijiangming 也就是说内存已经释放了,但是 OS 不会再一次分配给这个进程?
    jiang1234321
        13
    jiang1234321  
    OP
       2017-11-24 12:30:03 +08:00
    @hxndg 方便贴出来博客的连接吗?一大段英文 get 不到重点
    jiang1234321
        14
    jiang1234321  
    OP
       2017-11-24 12:31:11 +08:00
    @wwqgtxx linux 平台的实现应该都是一样的吧
    lijiangming
        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 指向相同地址
    lijiangming
        17
    lijiangming  
       2017-11-24 14:02:27 +08:00
    @jiang1234321 复制错了,sizeof(int); 你可以测试一下
    hxndg
        18
    hxndg  
       2017-11-24 14:04:22 +08:00
    @jiang1234321
    额,不好意思啊,我博客太多隐私的东西了.
    简单来说就是不立刻还给系统,malloc 会自己保存一个很大的串来进行管理.
    有专门的函数控制这个,你可以搜索一下.
    owenliang
        19
    owenliang  
       2017-11-24 14:29:52 +08:00
    buffered/cached
    3dwelcome
        20
    3dwelcome  
       2017-11-24 15:53:54 +08:00   1
    free 会归还的。

    往大的看,linux 把空余的内存都利用起来了,所以一般是检测 swap 占用率,来确定当前内存的用量。
    往小的看,你可以尝试查看 cat /proc/[id]/status,里面有 vmpeak(进程启动后内存的最大占用量)和 vmsize(当前内存占用大小)

    或者你技术更好,就用 /proc/[id]/maps 自己算页面大小,看看 malloc 究竟占了你多少空间。
    3dwelcome
        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++写的代码,是可以这样看的。
    jiang1234321
        22
    jiang1234321  
    OP
       2017-11-24 19:36:39 +08:00
    @3dwelcome 多谢指导,再问一下,我启动程序的时候 top 看内存的时候 VIRT 直接到了 1523M,但是 RES 只有 15M,%MEM 也只有%0.8,这是什么原因?
    jiang1234321
        23
    jiang1234321  
    OP
       2017-11-24 19:37:37 +08:00
    @3dwelcome
    /proc/[id]/status 文件里面显示的是
    VmPeak: 1559568 kB
    VmSize: 1559568 kB
    datocp
        24
    datocp  
       2017-11-25 07:43:57 +08:00 via Android
    当年在 ddwrt 只有 ralink 的设备通过 echo drop_cache 使这个 32M 内存的 dlink600 具备无限回复内存的能力。而同样版本针对 tplink wa701 的只会越用越少,所以针对这种设备直接每天定时重启,因为过低的内存至少已知会导致 dnsmasq 崩溃。
    wanderer
        25
    wanderer  
       2017-11-26 01:17:26 +08:00
    madvise()
    a32b88z
        26
    a32b88z  
       2017-11-27 22:11:19 +08:00
    这种问题,还是不要探究的好。

    计算机专业的操作系统专业书可以看看了解下原理,至于你真的要完全搞明白 Linux 和其他 OS 是怎样管理内存的,没这必要,也不是普通人随随便便就能搞明白的。就算搞明白了对你也没什么用。

    你只要知道操作系统自己会「智能」管理内存就行了。如果你自己开发程序,特别是 c、c++之类的,特别注意不要 leak 内存就 ok.

    如果是 linux 系统管理,把重点放在观察 ps 命令里面那个 rss。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     878 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 22:06 PVG 06:06 LAX 14:06 JFK 17:06
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86