能否在不同进程间使用函数指针?

7
我知道每个进程都会创建自己的内存地址空间,但是我想知道,
如果进程A有如下函数:
int DoStuff() { return 1; }

"以及一个指针 typedef,例如:"
typedef int(DoStuff_f*)();

一个类似这样的getter函数:
DoStuff_f * getDoStuff() { return DoStuff; }

一种通过 boost::interprocess 与 Process B 进行通信的神奇方式是什么?
将函数指针传递给进程 B 并直接调用来自进程 A 的 DoStuff,这种做法可行吗?

2
请说明您所使用的操作系统。对于vxWorks和Linux而言,这个问题的答案是非常不同的。 - kmarsh
2
同意 - 所有的“否”回答应该被理解为“不可移植”,和/或“不适用于我的操作系统”。在一些非常轻量级的操作系统平台上,没有受保护的内存,它将正常工作。 - Steve Jessop
我猜测这是Windows。我的假设基于早期Maciek的问题和函数命名风格 :) - Kirill V. Lyadvinsky
@onebyone:基本上,如果您正在运行没有虚拟地址空间的SOC,则可能是潜在的可能性。 - Martin York
6个回答

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的数据结构和全局内存!所以简短的答案是不,这不是你想要做的!此外,诸如 地址空间布局随机化 的安全措施可能会防止这些“技巧”起作用。你混淆了IPC和RPC。IPC用于通信数据,例如你的对象或一块文本。RPC用于在远程进程中执行代码。

好的,有陷阱处理程序,它们的作用是什么。 - user786

8
简而言之,您不能使用传递给另一个进程的函数指针。
函数的代码位于受保护的内存页面中,您无法对其进行编写。每个进程都具有隔离的虚拟地址空间,因此在另一个进程中,函数的地址无效。在Windows中,您可以使用this文章中描述的技术将代码注入到另一个进程中,但是Windows的最新版本会拒绝它。
您应该考虑创建一个库,而不是传递函数指针,该库将在两个进程中使用。在这种情况下,当您需要调用该函数时,可以向另一个进程发送消息。

1

如果你尝试从进程 B 使用进程 A 的函数指针,那么你实际上不会调用进程 A,而是会调用在进程 B 中与该地址相同的任何内容。如果它们是同一个程序,你可能会很幸运地得到相同的代码,但它将无法访问进程 A 中包含的任何数据。


1

一个函数指针对此无效,因为它只包含代码的起始地址;如果所需的代码不存在于另一个进程中,或者(由于诸如地址空间随机化之类的原因)位于不同的位置,则函数指针将无用;在第二个进程中,它将指向某些东西,或者什么也不指向,但几乎肯定不是您想要的位置。

如果你疯狂到敢这样做,你可以将实际指令序列复制到共享内存中,然后让第二个进程直接跳转到它 - 但即使你能让它工作,该函数仍将在进程B中运行,而不是进程A。

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


是的,消息传递。已经使用boost::interprocess实现了一个,想知道是否有“其他方法”。 - Maciek

1
这就是为什么人们发明了COM、RPC和CORBA等东西。它们每个都提供了这种通用的功能。正如你所猜测的那样,每个都从其他方面略有不同。
Boost IPC并不真正支持远程过程调用。它将使得将一个“变量”放入共享内存中,以便两个进程可以访问它,但如果您想使用getter/setter来访问该变量,则必须自己完成。
这些基本上都是包装器,用于生成一种“可接受”的版本,而您也可以在没有它们的情况下完成相同的操作。例如,在Windows中,您可以自己将变量放入共享内存中。在Linux中也可以做到同样的事情。 Boost库是围绕这些库编写的相对“薄”的库,它允许您为Windows或Linux编写相同的代码,但不会试图在此基础上构建很多内容。 CORBA(例如)是一个更厚的层,提供了一个相对完整的分布式环境。

0

如果两个进程在同一个应用程序中,则应该可以工作。如果您尝试在应用程序之间发送函数指针,则没有希望。

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


换句话说:即使我使用boost::interprocess、managed shared memory segment(例如),即使我传递指针,它仍然不会起作用,对吗? - Maciek
1
我对boost一无所知,但是在进程间通信时指针的传递方式并不重要。如果你的程序生成多个线程,你可以在它们之间传递指针。但如果你启动了两个独立的应用程序,则不能这样做。 - Graeme Perrow
请与我们分享您对“进程”和“应用程序”的定义。 - kmarsh
糟糕 - 我混淆了进程和线程。我的评论是正确的,但我的答案不是。我会进行更新。 - Graeme Perrow
不清楚你所说的“同一应用程序”是什么意思。如果它们在不同的进程中,那么没有任何保证这些都能正常工作。也许你的意思是它们是同一进程中的不同线程?在这种情况下,这可能会达到你想要的效果。但是OP明确指出了不同的进程... - Steven Schlansker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接