【问题标题】:Is it possible to use function pointers across processes?是否可以跨进程使用函数指针?
【发布时间】:2010-12-06 09:44:30
【问题描述】:

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

如果进程 A 有这样的功能:

int DoStuff() { return 1; }

还有一个指针类型定义,例如:

typedef int(DoStuff_f*)();

还有一个 getter 函数,例如:

DoStuff_f * getDoStuff() { return DoStuff; }

还有一种神奇的方式与进程 B 进行通信,例如 boost::interprocess

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

进程 A 的 DoStuff 直接来自进程 B?

【问题讨论】:

  • 请说明您正在处理的操作系统。对于 vxWorks 和 Linux,这个问题的答案非常不同。
  • 同意 - 所有“否”的答案都应理解为“不可移植”和/或“不在我的操作系统上”。在某些具有非常轻量级操作系统的平台上,没有受保护的内存,它可以正常工作。
  • 我想是 Windows。我的假设基于早期 Maciek 的问题和函数命名风格:)
  • @onebyone:基本上,如果您在没有虚拟地址空间的 SOC 上运行,它可能是可能的。

标签: c++ boost ipc


【解决方案1】:

没有。所有函数指针都是进程地址空间中的地址。它没有不同过程独有的内在标记。因此,即使您的函数指针恰好在您将其移至 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】:

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

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

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

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

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

        【讨论】:

        • 是的,消息传递。已经使用 boost::interprocess 实现了一个,想知道“其他方式”
        【解决方案5】:

        这就是人们发明 COM、RPC 和 CORBA 之类的东西的原因。它们中的每一个都提供了这种通用的能力。正如您所猜测的那样,每个人的工作都与其他人略有不同。

        Boost IPC 并不真正支持远程过程调用。它将允许将 变量 放入共享内存中,以便两个进程可以访问它,但是如果您想使用 getter/setter 来访问该变量,则必须自己做。

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

        【讨论】:

          【解决方案6】:

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

          如果您假设进程和线程是同一事物,那么我的原始答案是正确的,而事实并非如此。其他答案是正确的 - 不同的 进程 不能共享函数指针(或任何其他类型的指针,就此而言)。

          【讨论】:

          • 换句话说:即使我确实使用了 boost::interpcocess,托管共享内存段(例如),那么即使我传递了指针 - 它仍然无法工作,对吗?跨度>
          • 我对boost一无所知,但是你如何在进程之间传递指针并不重要。如果您的程序产生多个线程,您可以在它们之间传递指针。如果您要启动两个单独的应用程序,则不能。
          • 请与我们分享您对“过程”与“应用程序”的定义。
          • 糟糕——我混淆了进程和线程。我的评论是正确的,我的答案不是。我会更新的。
          • 不清楚你所说的同一个“应用程序”是什么意思。如果它们处于不同的进程中,则无法保证其中任何一个都会起作用。也许您的意思是它们是否是同一进程中的不同线程?在这种情况下,这可能会做你想做的事。但是 OP 非常明确地指出了单独的过程......
          猜你喜欢
          • 1970-01-01
          • 2019-03-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多