是否可以跨进程使用函数指针?

时间:2009-10-13 17:08:51

标签: c++ boost ipc

我知道每个进程都创建了自己的内存地址空间,但我想知道,

如果过程A具有如下功能:

int DoStuff() { return 1; }

和指针typedef如:

typedef int(DoStuff_f*)();

和getter函数如:

DoStuff_f * getDoStuff() { return DoStuff; }

和通过...进行通信的神奇方式...说boost :: interprocess

是否可以将函数指针传递给进程B并调用

直接从流程B处理A的DoStuff?

6 个答案:

答案 0 :(得分:8)

简而言之,您不能使用传递给另一个进程的函数指针。

功能代码位于受保护的内存页面中,您无法写入它们。并且每个进程都有隔离的虚拟地址空间,因此功能地址在另一个进程中无效。在Windows中,您可以使用this文章中描述的技术将代码注入另一个进程,但最新版本的Windows拒绝它。

您应该考虑创建一个将在两个进程中使用的库,而不是传递函数指针。在这种情况下,您可以在需要调用该函数时将消息发送到另一个进程。

答案 1 :(得分:8)

没有。所有函数指针都是进程地址空间中的地址。它没有内在标记,这是不同过程所特有的。因此,即使您的函数指针恰好在将其移动到B后仍然有效,它也会代表进程B调用该函数。

例如,如果你有

////PROCESS A////
int processA_myfun() { return 3; }
// get a pointer to pA_mf and pass it to process B

////PROCESS B////
int processB_myfun() { return 4; } // This happens to be at the same virtual address as pA_myfun
// get address from process A
int x = call_myfun(); // call via the pointer
x == 4;  // x is 4, because we called process B's version!

如果进程A和B运行相同的代码,您可能会在相同的地址处使用相同的函数 - 但您仍将使用B的数据结构和全局内存!所以简短的回答是,不,这不是你想要的方式!

此外,诸如address space layout randomization之类的安全措施可能会阻止这些“欺骗”工作。

你混淆了IPC和RPC。 IPC用于传递数据,例如对象或文本块。 RPC用于使代码在远程进程中执行。

答案 2 :(得分:1)

如果您尝试使用进程B中的进程A的函数指针,则不会调用进程A - 您将调用进程B中同一地址的任何内容。如果它们是相同的程序,您可能会很幸运,它将是相同的代码,但它不能访问进程A中包含的任何数据。

答案 3 :(得分:1)

函数指针不适用于此,因为它只包含代码的起始地址;如果有问题的代码在其他进程中不存在,或者(由于地址空间随机化等原因)位于不同的位置,则函数指针将无用;在第二个过程中,它会指向某个东西,或者什么都没有,但几乎肯定不是你想要的东西。

你可以,如果你是疯了^ Wdaring,将实际的指令序列复制到共享内存然后让第二个进程直接跳转到它 - 但即使你可以让它工作,该函数仍然会在进程中运行B,不是过程A.

听起来你想要的实际上是某种消息传递或RPC系统。

答案 4 :(得分:1)

这就是为什么人们发明了COM,RPC和CORBA之类的东西。他们每个人都提供这种一般的能力。正如你猜测的那样,每个人的工作都与其他工作有所不同。

Boost IPC并不真正支持远程过程调用。它将启用变量在共享内存中,以便它可以访问两个进程,但如果你想使用getter / setter访问该变量,你必须自己这样做。

这些都是基本的包装器,可以生成一个“可口”的版本,你可以在没有它们的情况下做。例如,在Windows中,您可以将变量放在共享内存中。您可以在Linux中执行相同的操作。 Boost库是一个相当“瘦”的库,它允许你为Windows或Linux编写相同的代码,但不会尝试在此基础上构建很多。 CORBA(例如)是一个更厚的层,提供了一个相对完整的分布式环境。

答案 5 :(得分:0)

如果两个进程都在同一个应用程序中,那么这应该可行。如果你试图在应用程序之间发送函数指针,那么你就不走运了。

如果你假设一个进程并且一个线程是同一个东西,那么我的原始答案是正确的,而他们不是。其他答案是正确的 - 不同的进程不能共享函数指针(或任何其他类型的指针)。