我不知道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