亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

go tool objdump怎么用

發布時間:2022-01-17 09:14:32 來源:億速云 閱讀:260 作者:iii 欄目:大數據

本篇內容主要講解“go tool objdump怎么用”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“go tool objdump怎么用”吧!

1.用go tool objdump,可以看到任意函數的機器碼、匯編指令、偏移。(go源碼下面有一個cmd/internal/goobj包,可以讀到.o文件的重定向信息,更好。)

2.修改里面的golang內部函數的相對跳轉,指向加載者相同的函數的地址(仍然可以用go tool objdump看到函數的初始地址),常見的有runtime.newobject、runtime.convT2Eslice、runtime.panicindex、runtime.morestack_noctxt等runtime系列函數。

3.修改golang類型指針偏移(當對象轉換成interface{}時候,需要一個類型指針),指向加載者相同的類型。

4.修改指向字符串,全局變量,自定義函數的偏移(一般都是相對偏移)。

5.寫入mmap,并執行。

整體思路是,通過修改偏移,復用加載者所用到的函數、golang內部函數、golang類型信息等。

缺點:

1.可以自定義類型,但是不能將這些類型的對象賦值到interface{}(加載者已定義的類型可以),比如使用fmt.Println打印這些對象(但是可以打印這些對象的成員)。因為golang內部的一些全局變量(比如golang類型)可能存在指針,而且開始就初始化了。

2.不能在函數外初始化全局變量。(可能的解決方法:定義一個入口函數,在里面初始化,或者讀取main.init函數,取出初始化代碼。)

優點:

仍然使用golang和golang編譯工具。

速度極快,體積極小。相當于復用了golang內部的調度器、內存分配器、類型系統等。

可以自定義。golang函數內的匯編足夠簡單,可以開發自己的工具來實現上面的思路。

golang本質就是GPM三個實體實現的調度。

G對應每個任務,P對應每個processor概念(就是會包含一堆的G,比如先執行G1,在執行G2)M對應系統線程,M(還包含系統棧之類的概念)綁定一個P之后就開始逐個運行P里面的G。

最基本的流程圖就是雨痕給的 

后面雨痕對于GPM三者的解釋也很到位。我這里不抄襲了。

2.初始化 

首先介紹的就是schedinit()里面主要是procresize函數。

這個procresize()就是調整系統里面P的數量。一般就是系統的cpu內核的數量,初始化時也實行多退少補的原則,只是退的時候要注意是否退出的P包含了當前P,如果是就需要一大堆的細節上的處理。

這里還有個所有P的管理結構

var allp [_MaxGomaxprocs + 1]*p

type schedt struct {

    pidle puintptr //  P  

    npidle uint32 //  P 

}

還有個提示,如果調用手動調用并修改runtime.GOMAXPROCS就會引發stopTheWorld以及startTheWorld,這兩個動作本身是比較好耗時的,之后在startTheWorld執行的procresize()也是比較耗時的。

3.任務 G/P 

先舉了個栗子,通過

go build -o test test.go

go tool objdump -s "main\.main" test

go add(x, y)會被匯編成類似

 CALL runtime.newproc(SB)

這種代碼

然后就去runtime找了。

newproc(獲取pc/ip地址以及入參等重要信息后)->newproc1

之后登場的G的數據結構

type g struct {

    stack stack  //執行棧

    sched gobuf  //用于保存執行現場

    goid  int64  //唯一序號

    gopc  uintptr //調用者 PC/IP

    startpc uintptr //任務函數

}

newproc1一開始就處理各種處理創建G,測試G,對齊地址,拷貝棧,保存現場的各種雜活兒。然后一個runqput(p, newg, true),被put進去了。

runqput有可能把g作為P.runnext,也可能放在末尾,也有可能丟到全局隊列。

稍微介紹了g通過p然后進行二級緩存復用的邏輯,類似cache/object,central的做法。分別對應gfget, gfput兩個函數。

所有的g 還有個全局應用allgs/allg,用來索引所有的G方便回收和shrinkstack。

補充了個細節只有本地的P隊列堆滿了才會丟到全局隊列,而且一次會丟本地隊列長度的一半,保證效率和多核均勻調度。

4.線程 M 

當結束runqput之后,開始wakep了, 

wake->startm->newm創建/或者notewakeup(&mp.park) 

newm->newosproc->linux調用

clone(cloneFlags,stk,unsafe.Pointer(mp),unsafe.Pointer(mp.g0),unsafe.Pointer(funcPC(mstart))) 開啟系統線程,并且入口函數是mstart

所有m會被添加到allm鏈表,不會被釋放,超過10000崩潰。

最后補充了兩個細節1:m也是有復用的,mput&mget使用1級緩存。

然后說不要創建太多m啊,time.Sleep比C.sleep(1)要好,之類的。

5.執行 

上面說到newm的時候會注冊系統線程并把mstart作為入口函數。

然后這里就講mstart

mstart -> 

mstart1 aquirep綁定p ->

schedule()兼顧幫助垃圾回收標記之類的各種雜活,findrunable,->

調用execute->

各種準備好棧JMP入函數入口地址PC->

各種調用結束后RET指令把預先壓入的goexit地址恢復到PC/IP->

將G返回服用鏈表->

重新schedule()

然后介紹了一下findrunable的主干:

1.通過runqget拿本地的P的東西, 

2.globrunqget 

3.檢查netpoll任務 

4.嘗試偷取其他P的任務。(基于CAS和atomicset弄的Work-Stealing算法)

… 

5.這后還會進行各種嘗試,如果實在沒有就stopm了。

Lockedg 

這是cgo的一個特定調用方式,會把當前的g和m綁定,而且只有在結束調用的時候才會松開。

一個m在調用schedule() 如果發現它是被某個G綁定的則會暫時休息。如果發現自己將要調用的G,是被別的m綁定的,則會將它喚醒,然后自己休眠。

所以每個cgo routine在調用完成之前都會有自己專屬的一個G調用。cgo因此會產生大量的m。

到此,相信大家對“go tool objdump怎么用”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

台南县| 辛集市| 青铜峡市| 蓬溪县| 富顺县| 沙雅县| 三台县| 东阿县| 三河市| 千阳县| 舒城县| 泾源县| 东兴市| 乌恰县| 昌图县| 山阳县| 呼伦贝尔市| 眉山市| 杂多县| 北票市| 呼和浩特市| 沙坪坝区| 吐鲁番市| 成安县| 朝阳区| 辽宁省| 准格尔旗| 安阳县| 余江县| 济宁市| 桃园县| 武定县| 盈江县| 南召县| 丹东市| 宁蒗| 平乐县| 东丰县| 玛纳斯县| 遂溪县| 准格尔旗|