golang動態加載原生代碼思路


 

update: 實現在此,歡迎star: https://github.com/dearplain/goloader

實現后的一些介紹:http://www.cnblogs.com/dearplain/p/8543804.html

 

golang動態加載原生代碼思路(非plugin,非so文件。使用mmap形式運行機器碼,可釋放)

 

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

2.修改里面的golang內部函數的相對跳轉,指向加載者相同的函數的地址(可以用cmd/internal/goobj包讀取所有函數的地址),常見的有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函數內的匯編足夠簡單,可以開發自己的工具來實現上面的思路。

 

用途:

一些過濾,路由,緩存,前端邏輯。有很多邏輯直接在前端處理更好。

直接處理,不想放到后端,不想重啟程序的服務,類似openresty。

「京東開濤」使用Nginx+Lua(OpenResty)開發高性能Web應用

京東三級列表頁持續架構優化—Golang+Lua(OpenResty)最佳實踐
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM