返回介绍

上卷 程序设计

中卷 标准库

下卷 运行时

源码剖析

附录

4.6.1 布局

发布于 2024-10-12 19:16:06 字数 7373 浏览 0 评论 0 收藏 0

栈由 [lo, hi) 描述的一块内存区间。

  lo           stackguard0                                  hi
  +------------+---------------------------------------------+
  | StackGuard |               stack frames                  |
  +------------+---------------------------------------------+
                                                 <--- RSP ----

指针 stackguard0、stackguard1 是一个预警边界。

与 SP 比较,以判断是否需要扩张。

其中 stckguard0 用于 Go,stackguard1 用于 C 栈。

// runtime2.go

type g struct {
    
    // Stack parameters.
    // stack describes the actual stack memory: [stack.lo, stack.hi).
    // stackguard0 is the stack pointer compared in the Go stack growth prologue.
    // It is stack.lo+StackGuard normally, but can be StackPreempt to trigger a preemption.
    // stackguard1 is the stack pointer compared in the C stack growth prologue.
    // It is stack.lo+StackGuard on g0 and gsignal stacks.
    // It is ~0 on other goroutine stacks, to trigger a call to morestackc (and crash).
    
    stack       stack
    stackguard0 uintptr
    stackguard1 uintptr
}
// Stack describes a Go execution stack.
// The bounds of the stack are exactly [lo, hi),
// with no implicit data structures on either side.

type stack struct {
    lo uintptr
    hi uintptr
}

初始栈大小是 2KB。

在 runtime.main 里,64 位上限是 1 GB。

Max stack size is 1 GB on 64-bit, 250 MB on 32-bit.

// stack.go

// The minimum size of stack used by Go code
_StackMin = 2048
// proc.go

func newproc1(fn *funcval, argp *uint8, narg int32, callergp *g, callerpc uintptr) *g {
    newg = malg(_StackMin)
}
// proc.go

func malg(stacksize int32) *g {
    newg := new(g)
    
    if stacksize >= 0 {
        stacksize = round2(_StackSystem + stacksize)
        systemstack(func() {
            newg.stack = stackalloc(uint32(stacksize))
        })
        
        newg.stackguard0 = newg.stack.lo + _StackGuard
        newg.stackguard1 = ^uintptr(0)
        *(*uintptr)(unsafe.Pointer(newg.stack.lo)) = 0
    }
    
    return newg
}

预留的 StackGuard 区域算是溢出缓冲。

微小型栈帧可在此区间分配。

// stack.go

// After a stack split check the SP is allowed to be this
// many bytes below the stack guard. This saves an instruction
// in the checking sequence for tiny frames.
_StackSmall = 128

// The stack guard is a pointer this many bytes above the
// bottom of the stack.
_StackGuard = 896 * sys.StackGuardMultiplier + _StackSystem

等级

栈在需要时进行扩张。

类似内存分配器管理方式,对小型栈按不同大小规格划分等级,以便复用。

// stack.go

// The minimum stack size to allocate.
// The hackery here rounds FixedStack0 up to a power of 2.

_FixedStack0 = _StackMin + _StackSystem
_FixedStack1 = _FixedStack0 - 1
_FixedStack2 = _FixedStack1 | (_FixedStack1 >> 1)
_FixedStack3 = _FixedStack2 | (_FixedStack2 >> 2)
_FixedStack4 = _FixedStack3 | (_FixedStack3 >> 4)
_FixedStack5 = _FixedStack4 | (_FixedStack4 >> 8)
_FixedStack6 = _FixedStack5 | (_FixedStack5 >> 16)
_FixedStack  = _FixedStack6 + 1

注释里已经给出大小和等级信息。

// malloc.go

// Number of orders that get caching. Order 0 is FixedStack
// and each successive order is twice as large.
// We want to cache 2KB, 4KB, 8KB, and 16KB stacks. Larger stacks
// will be allocated directly.
// Since FixedStack is different on different systems, we
// must vary NumStackOrders to keep the same maximum cached size.
//   OS               | FixedStack | NumStackOrders
//   -----------------+------------+---------------
//   linux/darwin/bsd | 2KB        | 4
//   windows/32       | 4KB        | 3
//   windows/64       | 8KB        | 2
//   plan9            | 4KB        | 3

_NumStackOrders = 4 - sys.PtrSize / 4 * sys.GoosWindows - 1 * sys.GoosPlan9

流程

分配及释放调用流程。

                                +--------------------------+          +------------------+
             +----------------> | mcache.stackcache[order] | -------> | stackcacherefill |
             |                  +--------------------------+          +------------------+
             |                                                                  |
           fixed                                                                |
             |                                                                  |
             |                                                                  v
       +------------+                                                 +------------------+
  ---> | stackalloc |                                                 | stackpoolalloc   |
       +------------+                                                 +------------------+
             |                                                        | stackpool[order] |
             |                       +-------------------+            +------------------+
           large              +----> | stackLarge.free[] |                      |
             |                |      +-------------------+                      |
             |                |                                                 |
             +----------------+                                                 |
                              |                                                 |
                              |      +-------------------+                      |
                              +----> | mheap.allocManual | <--------------------+
                                     +-------------------+
                                +--------------------------+          +-------------------+
             +----------------> | mcache.stackcache[order] | -------> | stackcacherelease |
             |                  +--------------------------+          +-------------------+
             |                                                                  |
           fixed                                                                |
             |                                                                  |
             |                                                                  v
       +-----------+                                                  +------------------+
  ---> | stackfree |                                                  | stackpoolfree    |
       +-----------+                                                  +------------------+
             |                                                        | stackpool[order] |
             |                       +-------------------+            +------------------+
           large              +----> | stackLarge.free[] |                      |
             |                |      +-------------------+                      |
             |                |                                                 |
             +----------------+                                                 |
                              |                                                 |
                              |      +------------------+                       |
                              +----> | mheap.freeManual | <---------------------+
                                     +------------------+

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文