V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
jiang1234321
V2EX  ›  Linux

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

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

    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   ·   实用小工具   ·   2629 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 04:42 · PVG 12:42 · LAX 20:42 · JFK 23:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.