美文网首页
GO学习笔记(四)初识runtime

GO学习笔记(四)初识runtime

作者: 温岭夹糕 | 来源:发表于2022-07-20 11:22 被阅读0次

前言

之前我们引入了协程这个概念,介绍完了进程线程与协程,再回过头来看看go程序的启动与初始化。
有如下coding
sleep.go

package main

import(
  "fmt"
  "os"
  "time"
)
func main(){
  fmt.Println(os.Getpid())
  go func (){
    time.Sleep(time.Second*100)
  }()
  time.Sleep(time.Second*1000)

}

进过编译后我们启动该程序,os.Getpid输出进程id,我们另开一个bash跟踪一下

ps -T -p <pid>
ps

我们可以看到该进程创建了3个线程,那么它是由谁创造的呢?往下走。

1.runtime

Go语言是一门有runtime的语言,runtime可以认为是为了实现额外的功能,而在程序运行时自动加载/运行的一些模块。从上面实验中我们知道一个GO程序启动的时候就会启动多个线程,而启动线程的就是GO runtime(为了实现额外的功能)。go的runtime package包是这样介绍的

Package runtime contains operations that interact with Go's runtime system, such as functions to control goroutines. It also includes the low-level type information used by the reflect package; see reflect's documentation for the programmable interface to the run-time type system.

任何一种高级语言都提供给用户写程序的形式,比如C和GO的主程序都是一个main函数,调用用户写的main函数的就是runtime。或者换句话说就是我们编译后的本地可执行代码,这些代码是运行在runtime当中(编译时会把runtime代码塞入可执行文件,entrypoint field的值设置成runtime里某个函数的起始地址),它负责管理内存分配、垃圾回收、栈处理、goroutine、channel、slice、map和反射等等。讲了这么多我们不如做实验看看
我们以笔记第一节的hello.go为例

package main
import (
    "fmt"
)
func main() {
    fmt.Println("hello world")
}

go build 编译成elf文件,再用readelf查看程序入口

readelf -h ./hello
readelf

我这里xshell没设置好,全中文,实际是entry_point字段,我这里是0x45bfc0,再用objdump反汇编查看汇编码(可执行文件是二进制elf格式)

objdump -S ./hello > out.txt
vim out.txt
/45bfc0  #vim搜索入口
out.txt

我们可以看到这条的指令是jmpq 4585e0 <_rt0_amd64>

跳转到4585e0执行_rt0_amd64这个函数,这个函数实际位置是在runtime包的asm_amd64.s汇编文件中 asm_amd64.s
这个函数又调用了 rt0_go函数 rt0_go
在同一个文件中,具体太长,简单概括一下
1.调用 x_cgo_init 函数。
2.调用 runtime.osinit 函数。

3.调用 schedinit 函数。
4.创建 run queue 和一个新的 G(goroutine)。
5.调用 runtime·mstart 函数。

实验小结

我们通过GO程序的汇编源码了解到GO的编译器是会把runtime和我们的代码编译在一起,证据就是程序的入口处就是跳转执行runtime的rt0_amd64函数,我们的代码是运行在runtime上的,runtime就相当于是介于用户态代码和操作系统之间的代理。
抽象成如下

runtime抽象概念 那么前文说的线程创建在哪里?线程创建就是调用系统调用创建线程,当然这张图也是前人所总结,我需要之后一步步验证他

复习下安装教程

虚拟机太难受,老电脑吃不消,斥巨资20买了7天云服务器,顺便复习下安装教程

useradd -m myname
passwd myname
usermod -a -G wheel myname (centos7 是wheel 不是sudo)
su myname
cd /tmp
wget https://golang.google.cn/dl/go1.18.4.linux-amd64.tar.gz
rm -rf /usr/local/go &&sudo tar -C /usr/local -xzf go1.18.4.linux-amd64.tar.gz
su root
vim /etc/profile // export PATH=$PATH:/usr/local/go/bin
go version

参考

1.go程序的启动和runtime的初始化
2.万文长字盛入浅出goruntime

相关文章

网友评论

      本文标题:GO学习笔记(四)初识runtime

      本文链接:https://www.haomeiwen.com/subject/nhaeirtx.html