Go标准库plugin源码分析----动态库使用

原创 2018年04月16日 14:21:41

本文公众号文章链接:https://mp.weixin.qq.com/s/2MKjUUJ6QxJieW4BGvhbxg



Go通常都是编译打包成一个可执行文件,好处是不需要考虑依赖库,一个可执行文件,拷贝就可以直接执行。

但还有些场景,如需要以插件形式加载,方便动态更新,热重启等情况。这些场景的需求,就带来了plugin库,动态库加载。


那么先看看plguin这个库的文档。文档为1.10版本



编译命令和普通的编译不一样,增加了参数-buildmode=plugin


另外plugin第一次加载时候,init函数会调用。(后面的源码分析中会分析)

注意:

1、plugin只init一次,并且不能closed。

2、目前只实现了linux平台和macos平台




文件很少,就只有两个(其实源码里有三个文件)

只提供了两个接口

Open:加载so库文件

Lookup:查找对应符号(包括func,var等)


文档中的示例



其中值得注意的是package是main



两个接口的使用,Open加载库文件,Lookup查找符号

示例中,有一个var,有一个func


那么再看下例子




这个里面多了一个init

使用





好了,下面看源码


源码目录



src/plugin/plugin.go



pluginpath:库的path

err:用于记录过程中的err

loaded:这个用于防止并发加载同一个库时候用

syms:这个记录的是库中所有的符号和其对应的值(可能是var、func等)




Open函数,封装了open函数



Lookup函数封装了lookup函数


src/plugin/plugin_stubs.go



这里是针对不支持平台的空实现,!linux,!darwin !cgo。可以看出,和文档中说的一样,非Linux,非darwin平台的时候编译成空实现。当然还有一个cgo,如果不支持cgo的话,也是无法实现plugin的。


那么看最后一个文件

src/plugin/plugin_dlopen.go



编译命令中,显示支持linux 和 darwin平台,当然要求是要支持cgo。

然后就是一个cgo的代码。其中封装了两个函数dlopen,dlsym。

其实看到这两个函数,就应该很熟悉了。



这个是linux种标准的动态链接加载接口。


当然plugin只实现了封装了dlopen,dlsym,两个函数。这个和文档中所提供的接口和描述是符合的。

只提供了加载,并没有提供关闭。


继续看源码



全局变量

pluginsMu:全局锁

plugins:保存加载的动态库


open



进入函数,一开始是一些字符串的转换。

重点是加锁后,会判断是否已经在加载,或者已经加载过的plugin。

这个时候,如果刚好plugin还在加载中,

<- p.loaded 会等待plugin加载完毕后,close掉p.loaded。

这种方式就是合并加载




这里就是调用了cgo代码pluginOpen,加载so库



初始化plugin结构体,并将其放入到全局的plugins这个map中。然后unlock全局锁。

继续,调用了cgo代码pluginLookup,查找init函数,并执行。




接着就是循环读取所有的符号,并将符号与其对应的值保存下来。保存在p.syms中。

最后close p.loaded,表示加载过程结束了。


lookup



所有的符号都保存在p.syms中,这个时候的查找,就只需要直接查找syms就可以了。



龚浩华

月牙寂道长

QQ 29185807

2018年04月16日

如果你觉得本文对你有帮助,可以转发分享到你的朋友圈,让更多人一起学习。

第一时间获取文章,可以关注本人公众号:月牙寂道长,也可以扫码关注


版权声明:本文为作者原创,如需转载请通知本人,并标明出处和作者。擅自转载的,保留追究其侵权的权利。golang群:570992072。qq 29185807 个人公众号:月牙寂道长 公众号微信号yueyajidaozhang https://blog.csdn.net/screscent/article/details/79959894

GO1.8特性---plugin(go 动态库)

简介: 在go1.8出现以前,一直觉得go语言不能像C/C++一样可以使用动态库的方式动态修改服务。每次升级操作都不得不重新编译整个工程,重新部署服务。这对于很多比较重型的服务来说是一个很致...
  • m0_38132420
  • m0_38132420
  • 2017-03-30 20:37:37
  • 3166

Golang官方如何支持加载动态库

Golang1.8官方支持加载动态库了,而且看起来功能很强大。 文档上面描述Plugin功能是协程并发安全的,而且支持高级数据类型(包括chan),同时不需要写任何C代码(以前或多或少需要写一些)。 ...
  • andylau00j
  • andylau00j
  • 2016-12-20 21:19:27
  • 6306

Go 语言标准库

  • 2018年04月09日 13:25
  • 1.72MB
  • 下载

使用golang的标准库搭建网站--2.模板解析

模板的解析既然是搭建网站,fmt.Fprintf(w, "Hello world, this is my first page!")这种方式肯定就不能用了,得解析模板才行。...
  • mybc724
  • mybc724
  • 2015-12-13 12:49:47
  • 920

深入源码分析go类型系统

深入源码分析go类型系统   Ø runtime/type.h    go类型描述的静态信息 //type  go类型最通用定义,go的类型系统通过这个数据结构来进行驱动 /...
  • hittata
  • hittata
  • 2016-03-17 17:23:23
  • 1872

GO语言标准库概览

Go标准库包含了大量包,提供了丰富广泛的功能特性。这里提供了概览仅仅是有选择性的且非常简单。本文发表后,标准库的内容还可能继续增加,因此 建议大家最好是通过在线查阅库API或使用godoc(包含在Go...
  • u011032846
  • u011032846
  • 2015-11-25 19:32:53
  • 788

Golang1.7动态库的使用,C和Golang的动态库以及使用

项目目录 root@working-srv:/data/code/src# tree project workspace/ project └── pro.go workspace/ └── main...
  • fyxichen
  • fyxichen
  • 2016-09-10 15:59:45
  • 5661

Go语言调用c动态库遇到的一些问题

背景:今天项目中需要在go里面调用c的动态库,首先代码中用Cgo实现了一个c函数,c函数中会调用到c动态库中的函数、代码在编译和运行的时候都出现了一错误。 package mode/* ...
  • luoyongxiao
  • luoyongxiao
  • 2017-09-20 22:06:49
  • 226

Golang 部分标准库说明

更多文章,请大家移步到新的博客:blog.haoitsoft.com,谢谢大家一直以来的支持!!!archive/tar 和 /zip-compress:压缩(解压缩)文件功能。fmt-io-bufi...
  • ningyuanhuo
  • ningyuanhuo
  • 2017-02-09 15:15:28
  • 1145

Go中使用动态库C/C++库

最近需要做一些在go中使用动态C++库的工作,经常碰到 示例代码目录结构(假设代码根目录为/home/gdc/cgotest): ----|bin: ----|pkg ----|src --...
  • xiaogugood
  • xiaogugood
  • 2014-07-18 17:23:58
  • 10129
收藏助手
不良信息举报
您举报文章:Go标准库plugin源码分析----动态库使用
举报原因:
原因补充:

(最多只允许输入30个字)