亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

golang調度程序如何以及為什么在runtime/proc.go:execute中遞歸地運行

golang調度程序如何以及為什么在runtime/proc.go:execute中遞歸地運行

Go
米琪卡哇伊 2023-07-31 15:43:36
我試圖分解 Go 調度程序的工作原理,我在runtime/proc.go中看到的是:該schedule函數調用execute運行一個 goroutine的注釋execute明確指出該函數永遠不會返回。它調用gogo匯編文件之一中定義的函數。該gogo函數執行跳轉到新 goroutine 的第一條指令的地址。當這個 goroutine 完成后,schedule函數會被再次調用,所以我們回到了步驟 1。如果我的理解是正確的,那么這個方案是如何避免堆棧溢出的呢?它與自動增加其大小的“無限”堆棧有關,還是我在這里遺漏了一些東西?
查看完整描述

1 回答

?
幕布斯6054654

TA貢獻1876條經驗 獲得超7個贊

所以我花了一些時間研究這個主題,現在可以嘗試回答我自己的問題。整個 goroutine 生命周期變得更加復雜:

  1. 新的 goroutine 在一個名為 的特殊 goroutine 中創建g0,它是線程的主 goroutine。任何對 的調用都會go func將堆棧從調用它的當前 Goroutine 更改為g0(這是在 中完成的proc.go:newproc)。

  2. 當創建 goroutine 時(在 中),它的堆棧(和/或程序計數器,PC)以看起來像是由函數調用的proc.go:newproc1方式構建。這樣做是為了保證當 goroutine 完成并返回時,它會返回到.goexitgoexit

  3. schedule調用 并選擇運行一個 goroutine 時,該execute函數將執行它(== 通過gogo匯編函數跳轉到其地址)。

  4. Goroutine 完成后,它返回goexit在匯編中實現的函數。

  5. 該匯編函數調用proc.go:goexit1(不確定為什么需要匯編中的這個額外步驟)。

  6. goexit1函數將當前堆棧更改為g0. 這是通過調用mcall(“機器線程調用”)來完成的,它執行參數中接收到的任何函數。在這種情況下,提供給的函數mcallgoexit0。

  7. 在匯編中實現的 跳轉到的堆棧幀 (SP)mcall的地址并執行to 。g0CALLgoexit0

  8. goexit0函數在 的上下文中執行g0。它將一個已完成的 goroutine 放入空閑 goroutine 列表中,并釋放其堆棧(如果之前已增加)。

  9. 然后再次goexit0調用schedule,選擇一個 goroutine 來運行,所以我們回到步驟 3。

所以這里確實似乎沒有遞歸。調度的 goroutine 本身從不調用schedule:這是由一個特殊的 goroutine 完成的g0。我仍然不確定我是否捕獲了所有細節,因此歡迎評論和其他答案。


查看完整回答
反對 回復 2023-07-31
  • 1 回答
  • 0 關注
  • 122 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號