可以說我有一個A.c
文件並將其編譯爲A.o
文件。 的A.c
文件如下:一起內存共享.o文件
int a;
void add(void)
{
}
的A.o
文件與B.o
形式的1.exe
文件。 A.o
文件與C.o
一起構成2.exe
文件。
,如果我在同一時間運行1.exe
和2.exe
我的問題,將在a
和add()
地址是這兩個.exe
文件一樣嗎?換句話說,內存中有兩個A.o
還是隻有一個?
可以說我有一個A.c
文件並將其編譯爲A.o
文件。 的A.c
文件如下:一起內存共享.o文件
int a;
void add(void)
{
}
的A.o
文件與B.o
形式的1.exe
文件。 A.o
文件與C.o
一起構成2.exe
文件。
,如果我在同一時間運行1.exe
和2.exe
我的問題,將在a
和add()
地址是這兩個.exe
文件一樣嗎?換句話說,內存中有兩個A.o
還是隻有一個?
您在內存中沒有任何重新定位的對象文件。
我猜你有一個Linux系統。如果在Windows上,原則保持不變,但細節不同。
接頭(稱爲建立兩者1.exe
和2.exe
)生成可執行ELF文件(由若干段的,特別是所謂的"text" segment爲機器代碼和只讀恆定的數據,並且"data" segment爲可變數據)。啓動該程序的系統調用是內存映射ELF文件的幾個段(幾乎與系統調用的一些mmap(2)
一樣)。
請注意,對於Linux可執行文件使用.exe
文件後綴很混亂且不常見。通常,Linux可執行文件根本沒有後綴,並以小寫字母開頭。
鏈接器已複製並將兩個A.o
文件重新分配到不同的東西(因爲relocation)。所以通常情況下,a
或add
的地址在1.exe
和2.exe
中是不同的,處理它們的機器指令也是如此。
每個process都有它自己的address space(可以用例如mmap(2)系統調用改變)。輸入cat /proc/1234/maps
來了解pid 1234進程的地址空間。也試試cat /proc/self/maps
來獲取運行該進程的地址空間cat
。
如果不是A.o
對象你有共享對象(或動態庫)libA.so
它的一些(mmap
-ed)段將共享(和其他人將使用copy on write技術),以及一些搬遷發生在動態鏈接時間(例如,在dlopen
期間,如果它是插件)。
a
和add
的地址將不一樣。你有兩個進程,因此在這個例子中有兩個內存拷貝。
它依賴於鏈接....默認情況下,鏈接總是動態的,所以當你加載兩個exe文件到內存中的文件A.o將表現爲可重入函數,並且它的唯一一個實例將在這兩個exe文件共享的內存中...
其類似printf函數...有太多printf任何diff diff文件,但一次只有一個實例運行在內存...
入函數不應該送你爲什麼要使用該.exe後綴,美必須照顧
任何數據損壞? – rubenvb
由於原始海報使用'.exe'後綴 –
啊,那麼OP可能在Windows上使用GCC,所有關於'mmap'和ELF的東西都是不相關的。 – rubenvb