十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
go可以在安卓运行的,github点抗 /golang/mobile,这是用golang做移动端开发的库,
疏附ssl适用于网站、小程序/APP、API接口等需要进行数据传输应用场景,ssl证书未来市场广阔!成为成都创新互联公司的ssl证书销售渠道,可以享受市场价格4-6折优惠!如果有意向欢迎电话联系或者加微信:13518219792(备注:SSL证书合作)期待与您的合作!
go是静态编译语言,不是脚本语言
汇编比较特殊,他主要应用的环境别人都替代不了,别的语言能干的事情没谁会傻到用汇编。这玩意一般用来做一些高级语言运行环境还没初始化的时候运行的程序比如BIOS,还有内核里需要操作一些特殊的寄存器的时候,比如x86下读写CR0,CR3之类的控制寄存器的情况,这些高级语言都没法办到。
我们都知道goroutine的在golang中发挥了很大的作用,那么当我们创建一个新的goroutine时,它是怎么一步一步创建的呢?都经历了哪些操作呢?今天我们通过源码来剖析一下创建goroutine都经历了些什么?go version 1.15.6
对goroutine最关键的两个函数是 newproc() 和 newproc1() ,而 newproc1() 函数是我们最需要关注的。
我们先看一个简单的创建goroutine的例子,找出来创建它的函数。
输出结果:
通过使用 go tool compile -S main.go 命令输出的汇编我们基本可以看到有一个 runtime.newproc() 函数的调用(CALL 是汇编调用函数指令) ,这个正是runtime创建goroutine的关键函数。
我们先看一个官方对newproc() 函数的注释说明。
通过官方注释,可得知以下信息:
创建一个goroutine,是通过调用一个 fn 函数来实现的,调用时需要指定参数大小
创建完后需要将goroutine放在一个运行队列(P的本地队列或全局队列)
编译器通过一个go关键字 实现对函数的调用
stack layout 是特殊的
函数是nosplit ,不允许分裂的
funcval 是一个结构体类型
可以看出newproc()函数只是对newproc1() 函数的一个封装。
getcallerpc() 函数用来获取调用者的program counter(PC) ,最终会转换为汇编实现调用,类似的还有getcallersp()。官方注释如下
getcallersp() 函数调用时结果是正确的,但随着随后堆栈的扩容和缩容结果很可能是错误的。一般规则是将 getcallersp() 的结果立即传递给nosplit函数,正如这里 newproc() 函数对 newproc1() 的调用方法一样。
对PC寄存器的介绍参考 这里 。
我们还是先看一下函数注释。
创建一个G(状态为 _Grunnable),从 fn 开始。其参数大小为 nargs 字节,从argp开始。
callerpc 是创建go 语句的地址,caller负责将新创建的g发送调度程序。
函数必须运行在系统栈上(go:systemstack),不允许 split,它和函数 newproc() 是连续一起的。
参数说明
fn: 要执行的函数
argp: 函数的第一个参数地址
narg: 参数总字节大小
callergp: 这里是g0
callerpc: caller PC, 创建go语句的地址
现在我们再看一下函数体内容
至此,goroutine已经创建成功并处于_Grunnable 状态,对于它的执行只需要有个P来执行就可以了。
这里再提醒一次,newproc1() 函数是运行在系统栈上,地址和 newproc() 一起且连续的。
对于字段 newg.sched.pc 值为赋值 goexit() 函数+1, 请参考 这里
这里重点理解下这几个字段的作用
newg.sched.sp
newg.sched.pc
newg.gopc
newg.startpc
理解SP PC 这些概念时,需要知道栈的布局 Stack frame layout 。
// Stack frame layout
//
// (x86)
// +------------------+
// | args from caller |
// +------------------+ - frame-argp
// | return address |
// +------------------+
// | caller's BP ( ) | ( ) if framepointer_enabled varp sp
// +------------------+ - frame-varp
// | locals |
// +------------------+
// | args to callee |
// +------------------+ - frame-sp
腾讯:汇编是深入理解 Go 的基础
程式计数器
本文出自:
单片机不像一些应用软件,和硬件结合十分紧密,必须要求“高效”,所以汇编语言是最好选择,其次就是C语言了。其他语言编译效率都太低,满足不了要求。