golang知识点整理(持续更新)
分段栈:
Go1.4之前的栈管理技术,运行时给每个goroutine分配8K的初始化栈内存;
在每个go函数之前有个代码块,检查已分配栈空间已不足,
不足的话会调用morestack函数来分配一段新的内存作栈空间,
然后将包括上一个栈地址等信息的struct和lessmore函数写入栈底,
接着重启gorouine,从将原来栈空间用光的函数开始执行(这里称为stack split)。
等该函数执行返回时,通过lessstack函数查找栈底部struct来调整栈指针,
使得返回原来栈空间,同时将该新栈段释放掉。
连续栈:
Go1.4之后使用连续栈,同样在每个函数入口进行栈溢出检查,
只是在栈溢出时会申请一个两倍于当前栈空间的内存空间,
然后把当前旧栈拷贝到新栈,释放旧栈空间,
最后程序重启goroutine并从引起重新分配栈段的函数继续执行。
实现栈拷贝的关键:
1. 只有在栈上分配的指针才能指向栈上的地址;
2. 需要知道栈上哪部分是指针,因为移动栈时需要把所有的指针指向新的目标地址;
原来Go运行时很多是C写的,大量运行时调用没有指针信息可用,这也是Go runtime被大规模重构的主要原因。