golang协程的本质

本文深入探讨了Go语言中的协程(Goroutine)实现,详细介绍了`g`结构体,包括栈空间记录、调度信息`sched`、协程状态`atomicstatus`以及协程ID`goid`等关键元素。通过这些内容,我们可以理解Go语言如何高效地管理和调度协程。
摘要由CSDN通过智能技术生成

        让我们来看下协程的源代码,在runtime2.go文件下,名字叫g。这边为了方便观看,把很多注释都删掉了,具体的可以自己去查看。

type g struct {
   stack       stack   // offset known to runtime/cgo
   stackguard0 uintptr // offset known to liblink
   stackguard1 uintptr // offset known to liblink

   _panic    *_panic // innermost panic - offset known to liblink
   _defer    *_defer // innermost defer
   m         *m      // current m; offset known to arm liblink
   sched     gobuf
   syscallsp uintptr // if status==Gsyscall, syscallsp = sched.sp to use during gc
   syscallpc uintptr // if status==Gsyscall, syscallpc = sched.pc to use during gc
   stktopsp  uintptr // expected sp at top of stack, to check in traceback

   param        unsafe.Pointer
   atomicstatus uint32
   stackLock    uint32 // sigprof/scang lock; TODO: fold in to atomicstatus
   goid         int64
   schedlink    guintptr
   waitsince    int64      // approx time when the g become blocked
   waitreason   waitReason // if status==Gwaiting

   preempt       bool // preemption signal, duplicates stackguard0 = stackpreempt
   preemptStop   bool // transition to _Gpreempted on preemption; otherwise, just deschedule
   preemptShrink bool // shrink stack at synchronous safe point

   asyncSafePoint bool

   paniconfault bool // panic (instead of crash) on unexpected fault address
   gcscandone   bool // g has scanned stack; protected by _Gscan bit in status
   throwsplit   bool // must not split stac
   activeStackChans bool
   parkingOnChan uint8
   raceignore     int8     // ignore race detection events
   sysblocktraced bool     // StartTrace has emitted EvGoInSyscall about this goroutine
   tracking       bool     // whether we're tracking this G for sched latency statistics
   trackingSeq    uint8    // used to decide whether to track this G
   runnableStamp  int64    // timestamp of when the G last became runnable, only used when tracking
   runnableTime   int64    // the amount of time spent runnable, cleared when running, only used when tracking
   sysexitticks   int64    // cputicks when syscall has returned (for tracing)
   traceseq       uint64   // trace event sequencer
   tracelastp     puintptr // last P emitted an event for this goroutine
   lockedm        muintptr
   sig            uint32
   writebuf       []byte
   sigcode0       uintptr
   sigcode1       uintptr
   sigpc          uintptr
   gopc           uintptr         // pc of go statement that created this goroutine
   ancestors      *[]ancestorInfo 
   startpc        uintptr         // pc of goroutine function
   racectx        uintptr
   waiting        *sudog         
   cgoCtxt        []uintptr      // cgo traceback context
   labels         unsafe.Pointer // profiler labels
   timer          *timer         // cached timer for time.Sleep
   selectDone     uint32         
   goroutineProfiled goroutineProfileStateHolder
   gcAssistBytes int64
}

        首先先看看stack的源代码:

type stack struct {
   lo uintptr
   hi uintptr
}

这个是记录了栈空间的下限和上限。之后我们来看看sched,他是个gobuf类型,

type gobuf struct {
   sp   uintptr
   pc   uintptr
   g    guintptr
   ctxt unsafe.Pointer
   ret  uintptr
   lr   uintptr
   bp   uintptr // for framepointer-enabled architectures
}

这个sp和pc学过机组的应该都不陌生 ,sp就是栈指针,他的含义就是我们的协程用到了栈的哪个地方,pc就是程序计数器,记录了我们运行到了哪个代码。之后我们再回来看下g的atomicstatus,记录了协程的状态,goid就是协程的id号。

        所以,协程的底层结构可以总结如下:

1:runtime中,协程的本质是一个g结构体。

2:g中的stack记录了堆栈的地址。

3:sched记录了目前程序的运行现场。

4:atomicstatus记录了协程的状态。

5:goid记录了协程的id

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值