二进制包如何知道go 版本_gops 是怎么和 Go 的运行时进行交互的?
本文基于 Go 1.13 和 gops 0.3.7.
gops 旨在幫助開發人員診斷 Go 流程并與之交互。它提供了跟蹤運行中的程序幾秒鐘的功能,可以通過獲取 CPU 配置文件?pprof,甚至可以直接與垃圾收集器進行交互。
發現
gops 提供發現服務,該服務能夠列出計算機上運行的 Go 進程。gops 不帶參數運行僅顯示 Go 進程。為了舉例說明,我啟動了一個程序,該程序可以計算高達一百萬的素數。這是流程發現的輸出:
295 1 gops go1.13 /go/src/github.com/google/gops/gops
168 1 prime-number* go1.13 /go/prime-number/prime-number
gops 看到程序啟動以及它自己的過程。基于此輸出,我們唯一需要的是進程 ID 就可以開始與程序進行交互。但是,讓我們了解 gops 是如何只過濾 Go 進程。
首先,gops 列出所有過程。然后,對于每個進程,它將打開二進制文件以讀取其符號表:
如果符號表包含?runtime.main(主 goroutine 的入口)或?main.main(我們程序的入口),則可以將其標記為 Go 程序。
有關符號表的更多信息,建議您閱讀我的文章 “Go:如何利用符號表”。要了解有關主 goroutine 的更多信息,建議您閱讀我的文章 “ Go:g0,Special Goroutine”。
gops 也會通過之前的符號表里面的?runtime.buildVersion獲取使用的 Go 版本。但是,由于可以從二進制文件中刪除符號表,因此 gops 需要另一種方法來檢測 Go 二進制文件。讓我們用剝離后的二進制文件再試一次:
295 1 gops go1.13 /go/src/..../gops
168 1 prime-number-s* unknown Go version /go/.../prime-number-s
如果程序正確地標記為 Go 二進制文件,則由于缺少符號表,因此無法再檢測 Go 版本。根據該可執行文件格式 - ELF,MZ 等 - gops 讀取尋找嵌入在二進制版本 ID 的部分。一旦發現完成,它就可以開始與程序進行交互。
交互
與其他 Go 程序進行交互的唯一條件是確保它們啟動了 gops 代理。該代理是一個簡單的偵聽器,將為 gops 請求提供服務。只需添加以下行即可:
if err:= agent.Listen(agent.Options {}); err!= nil {
log.Fatal(err)
}
然后,具有可用代理的任何程序都可以與 gops 進行交互。這是命令的示例?stats:
# gops stats 168
goroutines: 6210
OS threads: 9
GOMAXPROCS: 2
num CPU: 2
有關更多命令,您可以參考項目文檔。如果缺少該代理,則在與該代理進行交互時會收到錯誤消息:
Couldn't resolve addr or pid 168 to TCPAddress: couldn't get port for PID 168
該錯誤表明 gops 正在通過 TCP 尋找暴露的端點以便與程序進行通信。讓我們畫出軟件包的工作流程以了解其工作原理。
工作流程
gops 與 Go 程序之間的通信是通過 TCP 和 Go 程序的暴露端點進行的:
分配給每個程序的端口都寫在配置文件中,例如,?path/to/config/{processID}可以很容易讓 gops 知道暴露的端口。然后,gops 可以將命令標志發送到代理將在其中收集數據并進行響應的程序:
總結
以上是生活随笔為你收集整理的二进制包如何知道go 版本_gops 是怎么和 Go 的运行时进行交互的?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Pytorch神经网络理论篇】 01
- 下一篇: cursor用法java,Cursor的