上卷 程序设计
中卷 标准库
- bufio 1.18
- bytes 1.18
- io 1.18
- container 1.18
- encoding 1.18
- crypto 1.18
- hash 1.18
- index 1.18
- sort 1.18
- context 1.18
- database 1.18
- connection
- query
- queryrow
- exec
- prepare
- transaction
- scan & null
- context
- tcp
- udp
- http
- server
- handler
- client
- h2、tls
- url
- rpc
- exec
- signal
- embed 1.18
- plugin 1.18
- reflect 1.18
- runtime 1.18
- KeepAlived
- ReadMemStats
- SetFinalizer
- Stack
- sync 1.18
- atomic
- mutex
- rwmutex
- waitgroup
- cond
- once
- map
- pool
- copycheck
- nocopy
- unsafe 1.18
- fmt 1.18
- log 1.18
- math 1.18
- time 1.18
- timer
下卷 运行时
源码剖析
附录
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
4.6.1 布局
栈由 [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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论