Di Windows, ketika saya mengkompilasi kode C / C ++ dalam proyek DLL di MSVC saya mendapatkan 2 file:
MyDll.dll
MyDll.lib
di mana sejauh yang saya mengerti MyDll.lib
mengandung beberapa jenis tabel pointer yang menunjukkan lokasi fungsi di dll. Ketika menggunakan dll ini, katakanlah dalam file exe, MyDll.lib
tertanam ke dalam file exe selama hubungan sehingga dalam runtime itu "tahu" di mana fungsi berada MyDll.dll
dan dapat menggunakannya.
Tetapi jika saya mengkompilasi kode yang sama di Linux saya hanya mendapatkan satu file MySo.so
tanpa MySo.a
(setara dengan lib
file di Linux) jadi bagaimana cara file yang dapat dieksekusi di Linux tahu di mana fungsi berada MySo.so
jika tidak ada yang tertanam di dalamnya selama menghubungkan?
MSVC linker dapat menautkan bersama-sama file objek (.obj) dan objek perpustakaan (.lib) untuk menghasilkan .EXE atau .DLL.
Untuk menautkan dengan DLL, proses dalam MSVC adalah dengan menggunakan apa yang disebut perpustakaan impor (.LIB) yang bertindak sebagai perekat antara nama fungsi C dan tabel ekspor DLL (dalam DLL fungsi dapat diekspor dengan nama atau oleh ordinal - yang terakhir sering digunakan untuk API tidak berdokumen).
Namun, dalam kebanyakan kasus tabel ekspor DLL memiliki semua nama fungsi dan dengan demikian pustaka impor (.LIB) sebagian besar berisi informasi yang berlebihan (" fungsi impor ABC -> fungsi yang diekspor ABC ", dll).
Bahkan dimungkinkan untuk menghasilkan .LIB dari .DLL yang ada.
Linker di platform lain tidak memiliki "fitur" ini dan dapat terhubung dengan perpustakaan dinamis secara langsung.
sumber
Perbedaan yang Anda lihat adalah lebih detail implementasi - di bawah kap Linux dan Windows bekerja dengan cara yang sama - kode Anda memanggil fungsi rintisan yang terhubung secara statis di executable Anda dan tulisan rintisan ini kemudian memuat DLL / shlib jika perlu (jika terjadi penundaan Memuat , jika perpustakaan dimuat ketika program dimulai) dan (panggilan pertama) menyelesaikan simbol melalui
GetProcAddress
/dlsym
.Satu-satunya perbedaan adalah bahwa di Linux fungsi rintisan ini (yang disebut PLT bertopik) dihasilkan secara dinamis ketika Anda menautkan aplikasi Anda dengan perpustakaan dinamis (perpustakaan berisi informasi yang cukup untuk menghasilkannya), sedangkan di Linux mereka dihasilkan ketika DLL itu sendiri dibuat, dalam
.lib
file terpisah .Kedua pendekatan ini sangat mirip sehingga sebenarnya mungkin untuk meniru perpustakaan impor Windows di Linux (lihat proyek Implib.so ).
sumber
Di Linux, Anda meneruskan
MySo.so
ke linker dan hanya dapat mengekstraksi apa yang diperlukan untuk fase tautan, memasukkan referensi yangMySo.so
diperlukan pada saat run time.sumber
.dll
atau.so
shared libs (ditautkan dalam runtime), sementara.a
dan.lib
merupakan pustaka statis (ditautkan dalam waktu kompilasi). Ini tidak ada perbedaan antara Windows dan Linux.Bedanya, bagaimana mereka ditangani. Catatan: perbedaannya hanya di bea cukai, bagaimana mereka digunakan. Tidak akan terlalu sulit untuk membuat Linux dibangun berdasarkan cara Windows dan sebaliknya, kecuali bahwa praktis tidak ada yang melakukan ini.
Jika kita menggunakan dll, atau kita memanggil fungsi bahkan dari biner kita sendiri, ada cara yang sederhana dan jelas. Misalnya, dalam C, kita melihat bahwa:
Namun, pada tingkat ASM, mungkin ada banyak perbedaan. Misalnya, pada x86,
call
opcode dieksekusi, dan42
diberikan pada stack. Atau di beberapa register. Atau dimana saja. Tidak ada yang tahu itu sebelum menulis dll , bagaimana ini akan digunakan. Atau bagaimana proyek ingin menggunakannya, mungkin ditulis dengan kompiler (atau dalam bahasa!) Yang bahkan tidak ada sekarang (atau tidak diketahui oleh pengembang dll).Sebagai contoh, secara default, C dan Pascal menempatkan argumen (dan mendapatkan nilai balik) dari stack - tetapi mereka melakukannya dalam urutan yang berbeda . Anda juga dapat bertukar argumen antara fungsi Anda di register dengan beberapa - pengoptimalan-bergantung-kompiler.
Seperti yang Anda lihat dengan benar, kebiasaan Windows adalah membangun dll, kami juga membuat minimal
.a
/.lib
dengannya. Pustaka statis minimal ini hanya pembungkus, simbol (fungsi) dll yang dicapai melaluinya. Ini membuat konversi panggilan tingkat-asm yang diperlukan.Keuntungannya adalah kompatibilitas. Kerugiannya adalah bahwa jika Anda hanya memiliki .dll, Anda dapat mengalami kesulitan untuk mencari tahu, bagaimana fungsinya ingin dipanggil. Ini membuat penggunaan dll sebagai tugas peretasan, jika pengembang dll tidak memberi Anda
.a
. Dengan demikian, ini melayani sebagian besar tujuan penutupan, misalnya jadi apakah lebih mudah untuk mendapatkan uang tunai tambahan untuk SDK.Kerugian lainnya adalah daripada bahkan jika Anda menggunakan perpustakaan dinamis, Anda perlu mengkompilasi pembungkus kecil ini secara statis.
Di Linux, antarmuka biner dari dll adalah standar dan mengikuti konvensi C. Dengan demikian, tidak
.a
diperlukan dan ada kompatibilitas biner antara lib yang dibagikan, sebagai gantinya kami tidak memiliki kelebihan dari kebiasaan microsoft.sumber