【发布时间】:2011-12-15 22:23:26
【问题描述】:
假设我们有一个非常小的嵌入式系统,仅包含 linux 内核和一个作为 init 运行的静态链接二进制文件。我们希望二进制文件能够在运行时动态加载外部插件。
在 linux 上可以吗? Dlopen 仅适用于共享库和动态链接,因为静态二进制文件不会将任何符号导出到外部世界,那么还有其他方法吗?
【问题讨论】:
假设我们有一个非常小的嵌入式系统,仅包含 linux 内核和一个作为 init 运行的静态链接二进制文件。我们希望二进制文件能够在运行时动态加载外部插件。
在 linux 上可以吗? Dlopen 仅适用于共享库和动态链接,因为静态二进制文件不会将任何符号导出到外部世界,那么还有其他方法吗?
【问题讨论】:
您可以将“插件”作为子进程运行,并通过 IPC(共享内存、管道等)进行通信。
它们将存在于自己的进程空间中,因此您不能直接调用其中的函数(此外,如果它们也是静态链接的,则除了 main 之外,您将没有任何函数入口点,您可以到达),但您可以(例如)通过命名管道发送命令,或在共享内存结构中传递数据。
请注意,在您加载第二个二进制文件的那一刻,您已经失去了静态链接的主要好处之一(因为现在您已经加载了 libc 的两个副本),因此您可能只想考虑咬紧牙关并使用动态链接。在添加动态链接支持时,您将消耗 100K,但 GNU libc 大约为 2M,因此如果您正在加载一个插件,您可能已经节省了 180 万;对于您加载的每个额外插件,您将节省大约 2M。
【讨论】:
Dlopen 仅适用于共享库和动态链接,因为静态二进制文件不会将任何符号导出到外部世界
您可以在使用glibc 时从静态链接的二进制文件中打开共享库。如果您需要插件从主可执行文件中引用符号,则必须将指向它们的指针传递给插件,类似于this。
还有其他方法吗?
您也可以编写自己的模块加载器。 Linux 内核会这样做,Xorg 也是如此。
【讨论】: