Golang runtime初探

可以使用docker构造自己的环境:

Dockerfile

FROM centos
RUN yum install golang -y 
&& yum install dlv -y 
&& yum install binutils -y 
&& yum install vim -y 
&& yum install gdb -y
//构造image, Dockerfile所在目录
sudo docker build -t test .
//一定要带上权限参数privileged , 因为docker限制了dlv的权限
sudo docker run -it --privileged test

  

下面是本地本机安装,不用docker

先安装dlv

git clone https://github.com/derekparker/delve.git
cd delve/cmd/dlv/

go build
go install 

  

由于我安装的go version相对dlv版本比较新,所以需要添加参数忽略版本比较

[jet@192 study]$ ./dlv exec ./main
Version of Delve is too old for this version of Go (maximum supported version 1.14, suppress this error with --check-go-version=false)
[jet@192 study]$ ./dlv exec ./main --check-go-version
Version of Delve is too old for this version of Go (maximum supported version 1.14, suppress this error with --check-go-version=false)
[jet@192 study]$ ./dlv exec ./main --check-go-version=false
Type 'help' for list of commands.
(dlv) b *0x464540
Breakpoint 1 set at 0x464540 for _rt0_amd64_linux() /usr/lib/golang/src/runtime/rt0_linux_amd64.s:8
(dlv) b runqput
Breakpoint 2 set at 0x440e93 for runtime.runqput() /usr/lib/golang/src/runtime/proc.go:5126
(dlv) brunqget
Command failed: command not available
(dlv) b runqget
Breakpoint 3 set at 0x4412c0 for runtime.runqget() /usr/lib/golang/src/runtime/proc.go:5238
(dlv) b globrunqput
Breakpoint 4 set at 0x43a966,0x43b52e,0x43c9d0,0x43e51c,0x45a906,0x45b554 for runtime.injectglist() /usr/lib/golang/src/runtime/proc.go:5017
(dlv) b globrunqget

  

[jet@192 study]$ readelf -h main
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x464540
  Start of program headers:          64 (bytes into file)
  Start of section headers:          456 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         7
  Size of section headers:           64 (bytes)
  Number of section headers:         25
  Section header string table index: 3
[jet@192 study]$ dlv exec ./main
bash: dlv: command not found...
[jet@192 study]$ ./dlv exec ./main
Version of Delve is too old for this version of Go (maximum supported version 1.14, suppress this error with --check-go-version=false)
[jet@192 study]$ ./dlv exec ./main --check-go-version
Version of Delve is too old for this version of Go (maximum supported version 1.14, suppress this error with --check-go-version=false)
[jet@192 study]$ ./dlv exec ./main --check-go-version=false
Type 'help' for list of commands.
(dlv) b *0x464540
Breakpoint 1 set at 0x464540 for _rt0_amd64_linux() /usr/lib/golang/src/runtime/rt0_linux_amd64.s:8
(dlv) b runqput
Breakpoint 2 set at 0x440e93 for runtime.runqput() /usr/lib/golang/src/runtime/proc.go:5126
(dlv) brunqget
Command failed: command not available
(dlv) b runqget
Breakpoint 3 set at 0x4412c0 for runtime.runqget() /usr/lib/golang/src/runtime/proc.go:5238
(dlv) b globrunqput
Breakpoint 4 set at 0x43a966,0x43b52e,0x43c9d0,0x43e51c,0x45a906,0x45b554 for runtime.injectglist() /usr/lib/golang/src/runtime/proc.go:5017
(dlv) b globrunqget
Breakpoint 10 set at 0x440c53 for runtime.globrunqget() /usr/lib/golang/src/runtime/proc.go:5040
(dlv) c
> _rt0_amd64_linux() /usr/lib/golang/src/runtime/rt0_linux_amd64.s:8 (hits total:1) (PC: 0x464540)
Warning: debugging optimized function
     3: // license that can be found in the LICENSE file.
     4:
     5: #include "textflag.h"
     6:
     7: TEXT _rt0_amd64_linux(SB),NOSPLIT,$-8
=>   8:         JMP     _rt0_amd64(SB)
     9:
    10: TEXT _rt0_amd64_linux_lib(SB),NOSPLIT,$0
    11:         JMP     _rt0_amd64_lib(SB)
(dlv) bt
0  0x0000000000464540 in _rt0_amd64_linux
   at /usr/lib/golang/src/runtime/rt0_linux_amd64.s:8
1  0x0000000000000000 in ???
   at :0
   error: NULL address
(truncated)
(dlv) c
> runtime.runqput() /usr/lib/golang/src/runtime/proc.go:5126 (hits total:1) (PC: 0x440e93)
Warning: debugging optimized function
  5121: // runqput tries to put g on the local runnable queue.
  5122: // If next is false, runqput adds g to the tail of the runnable queue.
  5123: // If next is true, runqput puts g in the _p_.runnext slot.
  5124: // If the run queue is full, runnext puts g on the global queue.
  5125: // Executed only by the owner P.
=>5126: func runqput(_p_ *p, gp *g, next bool) {
  5127:         if randomizeScheduler && next && fastrand()%2 == 0 {
  5128:                 next = false
  5129:         }
  5130:
  5131:         if next {
(dlv) bt
0  0x0000000000440e93 in runtime.runqput
   at /usr/lib/golang/src/runtime/proc.go:5126
1  0x000000000045d95f in runtime.newproc.func1
   at /usr/lib/golang/src/runtime/proc.go:3531
2  0x000000000043cbae in runtime.newproc
   at /usr/lib/golang/src/runtime/proc.go:3527
3  0x00000000004611b4 in runtime.rt0_go
   at /usr/lib/golang/src/runtime/asm_amd64.s:220
(dlv) c
> runtime.runqget() /usr/lib/golang/src/runtime/proc.go:5238 (hits total:1) (PC: 0x4412c0)
Warning: debugging optimized function
  5233:
  5234: // Get g from local runnable queue.
  5235: // If inheritTime is true, gp should inherit the remaining time in the
  5236: // current time slice. Otherwise, it should start a new time slice.
  5237: // Executed only by the owner P.
=>5238: func runqget(_p_ *p) (gp *g, inheritTime bool) {
  5239:         // If there's a runnext, it's the next G to run.
  5240:         for {
  5241:                 next := _p_.runnext
  5242:                 if next == 0 {
  5243:                         break
(dlv) bt
0  0x00000000004412c0 in runtime.runqget
   at /usr/lib/golang/src/runtime/proc.go:5238
1  0x000000000043ae05 in runtime.schedule
   at /usr/lib/golang/src/runtime/proc.go:2664
2  0x0000000000437373 in runtime.mstart1
   at /usr/lib/golang/src/runtime/proc.go:1179
3  0x00000000004372ae in runtime.mstart
   at /usr/lib/golang/src/runtime/proc.go:1119
4  0x00000000004611bb in runtime.rt0_go
   at /usr/lib/golang/src/runtime/asm_amd64.s:225
(dlv) c
> runtime.goschedImpl() /usr/lib/golang/src/runtime/proc.go:5016 (hits total:1) (PC: 0x43b52e)
Warning: debugging optimized function
  5011: // Put gp on the global runnable queue.
  5012: // Sched must be locked.
  5013: // May run during STW, so write barriers are not allowed.
  5014: //go:nowritebarrierrec
  5015: func globrunqput(gp *g) {
=>5016:         sched.runq.pushBack(gp)
  5017:         sched.runqsize++
  5018: }
  5019:
  5020: // Put gp at the head of the global runnable queue.
  5021: // Sched must be locked.
(dlv) bt
0  0x000000000043b52e in runtime.globrunqput
   at /usr/lib/golang/src/runtime/proc.go:5016
1  0x000000000043b52e in runtime.goschedImpl
   at /usr/lib/golang/src/runtime/proc.go:2849
2  0x000000000043b7f4 in runtime.gopreempt_m
   at /usr/lib/golang/src/runtime/proc.go:2880
3  0x00000000004495fc in runtime.newstack
   at /usr/lib/golang/src/runtime/stack.go:1040
4  0x000000000046144f in runtime.morestack
   at /usr/lib/golang/src/runtime/asm_amd64.s:449
5  0x00000000004611b4 in runtime.rt0_go
   at /usr/lib/golang/src/runtime/asm_amd64.s:220
(dlv)

  可以看到

func runqput 函数里面对于goroutine他们的顺序是 runnext ---> runq ---> global queue

randomizeSchuduler 是race测试开关用的,可以忽略

原文地址:https://www.cnblogs.com/studyNT/p/14774641.html