Golang插件加载与初始化机制详解
Golang插件加载与初始化机制详解 在插件/plugin_dlopen.go代码的’func open(name string)'函数中,当加载插件(使用-buildmode=plugin选项编译)时,在调用C.pluginOpen(这仅仅是dlopen()的包装器)之后,当lastmoduleinit函数被调用时,全局变量’var firstmoduledata moduledata’中会出现一个描述刚刚加载的插件的结构体。
根据我对运行时源代码的理解,某些代码会读取.so文件的.init_array节并执行导出的go.link.addmoduledata函数,该函数的指针位于.init_array节中。
请问,在加载.so文件时,运行时中的哪些代码会将插件添加到firstmoduledata变量中?
谢谢。
更多关于Golang插件加载与初始化机制详解的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于Golang插件加载与初始化机制详解的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go运行时中,插件加载过程中将模块数据添加到firstmoduledata的关键代码位于runtime/plugin.go和相关的运行时初始化逻辑中。当调用plugin.Open()时,运行时通过以下步骤将插件模块数据链接到主程序:
-
在
open函数中调用C.pluginOpen(即dlopen)加载共享库后,运行时通过ELF文件的.init_array节找到并执行go.link.addmoduledata函数。 -
go.link.addmoduledata函数(在插件编译时由Go工具链插入)会调用运行时的内部函数addmoduledata,该函数将插件的moduledata结构添加到模块链表中。
具体来说,在运行时源代码中,addmoduledata函数(位于runtime/symtab.go或相关文件中)负责将新加载模块的数据链接到已有的模块数据链。firstmoduledata是一个全局变量,指向第一个模块的数据(通常是主程序),而新模块通过moduledata.next字段被添加到链中。
以下是相关代码逻辑的简化示例,说明模块数据如何被添加:
// 在运行时中,addmoduledata 函数大致如下:
func addmoduledata(datap *moduledata) {
// 将新模块数据插入链表
datap.next = firstmoduledata
firstmoduledata = datap
}
当插件被加载时,其对应的moduledata(包含符号表、类型信息等)通过上述方式被添加到firstmoduledata链中,使得运行时能够解析插件中的符号和类型。这一过程发生在插件初始化阶段,通过.init_array中的代码触发。
因此,在open函数调用C.pluginOpen后,插件的初始化代码(包括go.link.addmoduledata)会自动执行,从而更新firstmoduledata。无需在open函数中显式处理。

