xiaohanliang
OS
OS
  • hi
  • PROCESS
    • 0. 你的程序是怎么用内存的
    • 1. 为什么内存要区分堆与栈
    • 2. 什么叫你的程序
    • 3. 搞玄学?看看进程切换
    • 4. 进程是怎样调度的
    • 5. 理解进程线程有啥用
    • 6. 没有人真正见过的进程通信
    • 7. [WIP]mutex的起源CAS
    • 8. [WIP]mutex的下一步信号量
    • 9. [WIP]如何人为制造死锁
    • 10. 怎么什么东西都是fd
    • 11. IO各种模型
    • 12. Epoll内部是怎么工作的
  • NETWORK DEVICES
    • 1. 一个新的namesapce
    • 2. veth对讲机
    • 3. 如何靠网桥连接对讲机
    • 4. 左耳进右耳出的tun设备
    • 5. 如何用iptables改包头
    • 6. 在ip报头上再包个头
    • 7.如何用vxlan隧道分割局域网
    • 8. 通过多播组的方式获取mac
    • 9. 自动维护的fdb/arp表
    • 10. [WIP]macvlan网卡
Powered by GitBook
On this page
  • introduction
  • 栈
  • 堆

Was this helpful?

  1. PROCESS

1. 为什么内存要区分堆与栈

introduction

大家都是内存条, 为什么要区分堆区与栈区. 我之前在go语言的时候提过这些概念: Goroutine的默认栈大小是2K, 栈扩张, 以及Go语言里一部分变量可能会逃逸, 即栈区变堆区, 那么为什么要把同样的内存条划出两个区呢?

栈

当时在汇编语言里学过, 如果把地址加一, 就能获得一个地址的新内存, 用来存放变量, 同样的我们pop一下就能释放一个地址. 这个道理在Go语言里面使用, 我们通过这种方式使用着2K大小的G栈.

这种做法毫无疑问是最快的, esp(栈指针)上移/下移一位就能获得新的内存. 已经是硬件级别的速度了, 如果我们想要在函数里分配局部变量, 就这么做是最快的, 最后在函数结束的时候统一把ESP刷到顶就算回收完

既然栈这么快, 那我们只搞栈就好咯? 栈的问题是什么: 栈必须操作连续的内存, 你不能搞出带一个一个窟窿的内存, 在我们释放内存的时候你不能说给我把我之前的内存释放了, 但我留下. 你要释放, 就必须从tail开始释放. 这种特性导致我们只会在函数里, 分配局部变量的时候会用它, 因为函数是短暂的, 而且函数的清理比较"一体化" , 不会出现需要在中间挖窟窿的需求, 如果函数结束, 我们直接把函数所有用到的栈区从tail到head全部刷空就好了.

堆

有了函数局部变量这种, 能一次性全清理的情况, 自然就会有不能一次性全清空的情况, 设想我们有10个全局变量, 某个情况下我们可能会需要释放其中某一个, 这种情况就是我们上面说的挖窟窿, 其他不动, 删掉中间某一个. 而且发生时间非常不固定, 指不定某个时间下就要求清空其中某一个, 因此通过pop的那种一把刷清的情况就不存在. 这种情况下, 就出现了我们以前学过的malloc, 各种动态内存管理的机制.

我理解栈一定是最快的, 分配快, 释放快, 但pop操作要求连续, 因此不得已我们整出了堆的概念, 在C语言里堆内存要求手动的, 指定地址的, 去释放, 不停的在内存里挖窟窿非常容易出现内存零碎化的情况, 并且也容易产生内存忘记释放(内存泄露)的问题

Previous0. 你的程序是怎么用内存的Next2. 什么叫你的程序

Last updated 4 years ago

Was this helpful?