我不知道linux进程是否可以调用位于另一个进程的内存中的代码?Linux:是否可以在进程之间共享代码?
假设我们在进程A中有一个函数f(),并且我们希望进程B调用它。我想过的是,使用带MAP_SHARED和PROT_EXEC标志的mmap映射包含函数代码的内存,并将指针传递给B,假设f()不会从A二进制文件调用任何其他函数。它会工作吗?如果是,那么我如何确定内存中f()的大小?
===编辑===
我知道,共享库将做到这些,但我不知道是否有可能在进程之间动态共享代码。
我不知道linux进程是否可以调用位于另一个进程的内存中的代码?Linux:是否可以在进程之间共享代码?
假设我们在进程A中有一个函数f(),并且我们希望进程B调用它。我想过的是,使用带MAP_SHARED和PROT_EXEC标志的mmap映射包含函数代码的内存,并将指针传递给B,假设f()不会从A二进制文件调用任何其他函数。它会工作吗?如果是,那么我如何确定内存中f()的大小?
===编辑===
我知道,共享库将做到这些,但我不知道是否有可能在进程之间动态共享代码。
是的,您可以这样做,但第一个进程必须首先通过mmap
和内存映射文件或使用shm_open
创建的共享区域创建共享内存。
如果您正在共享编译代码,那么这就是共享库创建为。您可以通过普通的方式与他们进行链接,共享将自动发生,或者您可以使用dlopen
(例如,用于插件)手动加载它们。
更新:
由于代码已经由编译器产生的,那么你将有搬迁担心。编译器不会生成任何可以正常工作的代码。它预计.data
部分位于某个位置,并且.bss
部分已归零。 GOT将需要填充。任何静态构造函数都必须被调用。
总之,你想要的可能是dlopen
。这个系统允许你像打开一个文件一样打开共享库,然后按名称提取函数指针。程序库中的每个程序都将共享代码段,从而节省内存,但每个程序都将拥有自己的数据段副本,因此它们不会相互干扰。
请注意,您需要使用-fPIC
来编译您的库代码,否则您将无法获得任何代码共享(实际上,许多架构的链接器和动态加载器可能不支持不是PIC的库) 。
标准方法是将代码f()
置于共享库libfoo.so
中。然后,你既可以链接到该库(例如,通过建立程序甲与gcc -Wall a.c -lfoo -o a.bin
),或动态地加载(例如,在程序乙)使用dlopen(3)然后检索的f
使用dlsym
地址。
当你编译一个共享库要:
gcc -Wall -fPIC -c foo1.c -o foo1.pic.o
每个源文件foo1.c
编译成position independent code,同样为foo2.c
到foo2.pic.o
libfoo.so
与gcc -Wall -shared foo*.pic.o -o libfoo.so
;注意到可以链接附加共享库lbfoo.so
(例如通过附加-lm
到连接命令)你可以通过mmap
来玩疯狂的技巧 - 其他一些/proc/1234/mem
但这是不合理的。使用共享库。
PS。你可以dlopen
大量(数十万)共享对象lib*.so
文件;你可能想要dlclose
他们(但实际上你不必)。
这是可能的,但这正是共享库的用途。
另外,请注意您需要检查两个进程的共享内存地址是否相同,否则任何引用都是“绝对”(即指向共享代码中的某个指针)。和共享库一样,代码的位必须是相同的,并且与所有共享内存一样,如果修改任何共享内存,则需要确保不会“混淆”其他进程记忆。
根据生成的实际代码以及可用信息的级别,确定函数的大小范围从“硬”到“几乎不可能”。调试符号将具有函数的大小,但要注意,我已经看到编译器会生成代码,其中两个函数共享相同的“返回”代码片段(也就是说,编译器会生成跳转到具有相同代码位的另一个函数返回结果,因为它节省了几个字节的代码,并且无论如何已经有一个跳转[例如编译器必须跳转的if/else])。
不是直接。请使用动态库或[RPC](http://en.wikipedia.org/wiki/Remote_procedure_call)。 – 2013-02-27 14:13:07
这正是库的用途。根据你将要完成的任务,[IPC](http://www.tldp.org/LDP/lpg/node7.html)也可能会这样做。 – KBart 2013-02-27 14:16:55
您想共享的代码是由编译器生成的,还是由您的程序生成的? – ams 2013-02-27 14:22:16