有一些帖子和文章聲稱它已加載一次到物理記憶體,其他行程僅在加載時將其(隨機)虛擬地址映射到它: Libc 共享庫如何加載到記憶體中并在行程之間共享?
但是我用我的小型共享庫做了自己的小實驗,結果并不像預期的那樣:
1-我創建了一個名為 的共享庫libadd.so,代碼如下:
int add(int a){ return a;}
2- Made main.cwhich uses libadd,這里是代碼:
while(1){
printf("%d\n", add(1));
sleep(1);
}
運行將按預期每秒回圈main列印。2
3-在main運行時,我修改libadd.so為并在單獨的行程中return 0;重新運行。main
結果:
第一個行程繼續列印2,而新行程正在列印0。如果libadd.so真的只加載一次到物理記憶體,而其他行程只將它們的虛擬地址映射到它,那么兩個行程都應該已經列印了0,不是嗎?我的示例顯示在可執行記憶體中有此庫的 2 個不同副本。
uj5u.com熱心網友回復:
3- 在 main 運行時,我修改了 libadd.so 以回傳 0;并在單獨的行程中重新運行 main 。
作業系統注意到 libadd.so 在加載后發生了變化,它加載了新版本并將其鏈接到新行程。如果您運行另一個使用 libadd.so 的行程,并且 libadd.so 沒有更改,它將共享此快取副本。
舊版本也仍然加載在記憶體中。它將一直如此,直到沒有行程參考它。
uj5u.com熱心網友回復:
您的小實驗沒有考慮到可執行代碼位于一個完全不同的段中,名為.text,它不同于.data段(使用非零值全域變數預初始化)、.bss段(全域變數默認初始化為零)、堆疊和動態分配的記憶體。
行程之間共享的只是.text段(以及用于常量資料的段.rodata,本質上只是.text沒有PROT_EXEC權限集)。其他所有內容都被映射為行程私有記憶體。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/419662.html
標籤:
上一篇:為什么我要使用列舉作為型別?
