2009-10-13 46 views
7

我知道,每個進程創建它自己的內存地址空間,但是我想知道,是否有可能跨進程使用函數指針?

如果進程A是有這樣一個功能:

int DoStuff() { return 1; } 

和指針的typedef,如:

typedef int(DoStuff_f*)(); 

和吸氣功能,如:

DoStuff_f * getDoStuff() { return DoStuff; } 

,並通過與...進程B通信的神奇的方式說的boost ::進程間

將有可能通過函數指針來處理B和直接從進程B調用

進程A的DoStuff?

+2

請說明您正在處理的操作。對於這個問題的答案對於vxWorks和Linux來說是非常不同的。 – kmarsh 2009-10-13 17:22:40

+2

同意 - 所有「否」答案應該被理解爲「不可移植」,和/或「不在我的操作系統上」。在一些非常輕量級操作系統的平臺上,沒有受保護的內存,而且它會正常工作。 – 2009-10-13 17:44:47

+0

我想這是Windows。我基於早期Maciek的問題和功能命名風格的假設:) – 2009-10-13 18:04:18

回答

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用於使代碼在遠程進程中執行。

+0

ASLR的+1 - 我試圖記住有關的詳細信息。 – 2009-10-13 17:24:20

0

如果兩個進程都在同一個應用程序中,那麼這應該工作。如果您試圖在應用程序之間發送函數指針,那麼您運氣不佳。

如果你假設一個進程和一個線程是相同的東西,他們不是,我的原始答案是正確的。其他答案是正確的 - 不同的進程不能共享函數指針(或任何其他類型的指針,就此而言)。

+0

所以換句話說:即使我使用boost :: interpcocess,託管共享內存段(例如),那麼即使我通過指針 - 它仍然無法正常工作? – Maciek 2009-10-13 17:13:46

+1

我對boost的知識一無所知,但是如何在進程間交流指針並不重要。如果你的程序產生多個線程,你可以在它們之間傳遞指針。如果您啓動兩個單獨的應用程序,則不能。 – 2009-10-13 17:17:03

+0

請與我們分享您對「過程」與「應用」的定義。 – kmarsh 2009-10-13 17:23:26

8

總之,你不能使用傳遞給另一個進程的函數指針。

功能代碼位於內存的受保護頁面中,不能寫入它們。而且每個進程都有孤立的虛擬地址空間,所以在另一個進程中函數的地址是無效的。在Windows中,您可以使用this文章中描述的技術在另一個進程中注入代碼,但最新版本的Windows會拒絕它。

而不是傳遞函數指針,你應該考慮創建一個將在這兩個進程中使用的庫。在這種情況下,您可以在需要調用該函數時將消息發送到另一個進程。

1

如果您試圖使用流程B中的流程A的函數指針,那麼您將不會調用流程A--您可以調用流程B中相同地址的任何內容。如果它們是相同的程序,並且它將是相同的代碼,但它將無法訪問進程A中包含的任何數據。

1

函數指針對此不起作用,因爲它只包含代碼的起始地址;如果有問題的代碼在另一個進程中不存在,或者(由於地址空間隨機化等原因)處於不同位置,則函數指針將無用;在第二個過程中,它會指向某種東西,或者什麼都不指示,但幾乎可以肯定不是你想要的東西。

你可以,如果你瘋了^ Wdaring,將實際指令序列複製到共享內存上,然後讓第二個進程直接跳轉到它 - 但即使你可以得到這個工作,該函數仍然會運行過程B,而不是過程A.

這聽起來像你想要的實際上是某種消息傳遞或RPC系統。

+0

是的消息傳遞。已經實現了一個使用boost :: interprocess,想知道「其他方式」 – Maciek 2009-10-13 19:01:06

1

這就是人們發明COM,RPC和CORBA等東西的原因。他們每個人都具備這種通用的能力。正如你猜測的那樣,每個人的工作與其他人都有所不同。

Boost IPC並不真正支持遠程過程調用。它可以將變量放置在共享內存中,以便其可以訪問兩個進程,但是如果要使用getter/setter來訪問該變量,則必須自己執行該操作。

這些都是基本的包裝,以產生一個「可口」版本的東西,你可以做,但沒有他們。例如,在Windows中,您可以將變量放在共享內存中。你可以在Linux中做同樣的事情。 Boost庫是一個相當「瘦」的庫,可以讓你爲Windows或Linux編寫相同的代碼,但不會嘗試在此基礎上進行大量的構建。 CORBA(舉一個例子)是一個更厚的層,提供了一個相對完整的分佈式環境。

相關問題