Apakah objek/DLL yang dibagikan dimuat oleh proses yang berbeda ke dalam area memori yang berbeda?

Saya mencoba mencari tahu bagaimana sistem operasi menangani beberapa proses yang tidak terkait dengan memuat DLL/perpustakaan bersama yang sama. OS yang saya khawatirkan adalah Linux dan Windows, tetapi pada tingkat lebih rendah juga Mac. Saya berasumsi jawaban atas pertanyaan saya akan sama untuk semua sistem operasi.

Saya sangat tertarik dengan tautan eksplisit, tetapi saya juga ingin mengetahui tautan implisit. Saya kira jawaban keduanya juga akan sama.

Ini adalah penjelasan terbaik yang saya temukan sejauh ini mengenai Windows:

Sistem mempertahankan jumlah referensi per proses pada semua modul yang dimuat. Memanggil LoadLibrary akan menambah jumlah referensi. Memanggil fungsi FreeLibrary atau FreeLibraryAndExitThread akan mengurangi jumlah referensi. Sistem membongkar modul ketika jumlah referensinya mencapai nol atau ketika proses dihentikan (berapa pun jumlah referensinya). - http://msdn.microsoft.com/en-us/library/windows/desktop/ms684175%28v=vs.85%29.aspx

Tapi itu meninggalkan beberapa pertanyaan.

1.) Apakah proses yang tidak terkait memuat DLL yang sama secara berlebihan (yaitu, DLL ada lebih dari sekali di memori) alih-alih menggunakan penghitungan referensi? (Yaitu, ke dalam ruang alamat masing-masing proses seperti yang saya rasa saya memahaminya)

jika DLL dibongkar segera setelah suatu proses dihentikan, itu membuat saya percaya bahwa proses lain yang menggunakan DLL yang sama persis akan dimuat secara berlebihan ke dalam memori, jika tidak, sistem tidak boleh mengabaikan jumlah referensi.

2.) jika itu benar, lalu apa gunanya menghitung DLL ketika Anda memuatnya beberapa kali dalam proses yang sama? Apa gunanya memuat DLL yang sama dua kali ke dalam proses yang sama? Satu-satunya alasan yang masuk akal yang dapat saya kemukakan adalah jika EXE mereferensikan dua DLL, dan salah satu DLL mereferensikan yang lain, akan ada setidaknya dua panggilan LoadLibrar() dan dua FreeLibrary() untuk perpustakaan yang sama.

Saya tahu sepertinya saya menjawab pertanyaan saya sendiri di sini, tapi saya hanya berasumsi. Saya ingin tahu pasti.


person Brandon    schedule 28.06.2013    source sumber
comment
Pastikan Anda memahami memori virtual dan paging. Alamat aktual yang dilihat proses mungkin berbeda, terlepas dari apakah salinan perpustakaan terpisah dimuat atau tidak.   -  person Kerrek SB    schedule 29.06.2013


Jawaban (1)


Pustaka bersama atau DLL akan dimuat satu kali untuk bagian kode, dan beberapa kali untuk setiap bagian data yang dapat ditulisi [mungkin melalui "copy-on-write", jadi jika Anda memiliki sebagian besar memori yang sebagian besar dibaca, tetapi sebagian kecil bagian yang sedang ditulis, semua DLL dapat menggunakan bagian yang sama asalkan belum diubah dari nilai aslinya].

Namun, MUNGKIN DLL akan dimuat lebih dari satu kali. Ketika DLL dimuat, ia memuat alamat dasar, yang merupakan tempat kode dimulai. Jika kita mempunyai suatu proses, yang menggunakan, katakanlah, dua DLL yang, karena pemuatan sebelumnya, menggunakan alamat dasar yang sama [karena proses lain yang menggunakan ini tidak menggunakan keduanya], maka salah satu dari DLL tersebut harus dimuat lagi di alamat dasar yang berbeda. Bagi sebagian besar DLL, hal ini agak tidak biasa. Tapi itu bisa terjadi.

Inti dari penghitungan referensi setiap beban adalah memungkinkan sistem mengetahui kapan waktu yang aman untuk membongkar modul (ketika jumlah referensi adalah nol). Jika kita mempunyai dua bagian sistem yang berbeda, keduanya ingin menggunakan DLL yang sama, dan keduanya memuat DLL tersebut, Anda tentu tidak ingin menyebabkan sistem mogok ketika bagian pertama sistem menutup DLL tersebut. Namun kita juga tidak ingin DLL tersebut tetap berada di memori ketika bagian kedua dari sistem telah menutup DLL tersebut, karena itu akan membuang-buang memori. [Bayangkan aplikasi ini adalah proses yang berjalan di server, dan DLL baru diunduh setiap minggu dari server, jadi setiap minggu, DLL "terbaru" (yang memiliki nama berbeda) dimuat. Setelah beberapa bulan, seluruh memori Anda akan penuh dengan DLL "lama, tidak terpakai" aplikasi ini]. Tentu saja ada juga skenario seperti yang Anda jelaskan, di mana DLL memuat DLL lain menggunakan panggilan LoadLibrary, dan executable utama memuat DLL yang sama. Sekali lagi, Anda memerlukan dua panggilan FreeLibrary untuk menutupnya.

person Mats Petersson    schedule 28.06.2013
comment
Saya tidak mengerti apa yang Anda maksud tentang bagian data yang dapat ditulis atau copy-on-write. Saya memahami penghitungan referensi, hal yang membuat saya bingung adalah bagian tautan yang mengatakan Sistem membongkar modul ketika jumlah referensinya mencapai nol atau ketika proses dihentikan (berapa pun jumlah referensinya) . - person Brandon; 29.06.2013
comment
Benar, jadi ada hitungan referensi PER PROSES dan hitungan referensi lain berapa banyak proses yang menggunakan DLL tertentu. Jika proses terhenti (memanggil exit atau mengalami crash), maka jumlah referensi per proses tidak digunakan untuk menentukan data. Bagian data yang dapat ditulisi - variabel global dalam DLL harus per proses, atau berpotensi terjadi kebocoran yang sangat berbahaya antar proses. Cari di google copy-on-write, itu akan menjelaskan jauh lebih baik daripada yang saya bisa di posting di sini. - person Mats Petersson; 29.06.2013
comment
itu, karena pemuatan sebelumnya, menggunakan alamat dasar yang sama @MatsPetersson Saya agak bingung dengan ini. OS menggunakan alamat fisik bukan? Dan OS dapat memberikan alamat virtual yang berbeda untuk kedua DLL jika suatu proses menggunakan keduanya, lalu mengapa keduanya sama? - person pooya13; 10.02.2020
comment
Jika DLL dimuat dua kali, DLL harus (setidaknya sebagian) dimuat ke lokasi fisik yang berbeda, atau memiliki alamat virtual yang sama. Kemungkinan ada beberapa alamat absolut yang terlibat dalam kode, seperti penunjuk ke data atau fungsi, yang disimpan di suatu tempat, yang berarti alamat virtual harus sama untuk semua pengguna pemuatan fisik DLL. Dan OS umumnya tidak menggunakan alamat fisik. Ini memberikan alamat virtual ke wilayah memori fisik, tapi itulah satu-satunya waktu alamat fisik digunakan. - person Mats Petersson; 11.02.2020