Bagaimana cara kerja nomor SO (objek bersama)?

123

Saya sadar bahwa objek yang dibagikan di Linux menggunakan "nomor-nomor", yaitu bahwa berbagai versi objek yang dibagikan diberi ekstensi yang berbeda, misalnya:

  • example.so.1
  • example.so.2

Saya mengerti idenya adalah memiliki dua file berbeda sehingga dua versi perpustakaan dapat ada pada suatu sistem (sebagai lawan dari "Neraka DLL" pada Windows). Saya ingin tahu bagaimana ini bekerja dalam praktek? Seringkali, saya melihat bahwa example.sosebenarnya tautan simbolis ke example.so.2mana .2adalah versi terbaru. Lalu bagaimana suatu aplikasi tergantung pada versi yang lebih lama example.somengidentifikasinya dengan benar? Apakah ada aturan mengenai nomor apa yang harus digunakan seseorang? Atau ini hanya konvensi? Apakah itu masalahnya, tidak seperti di Windows di mana binari perangkat lunak ditransfer antar sistem, jika suatu sistem memiliki versi yang lebih baru dari objek yang dibagikan, itu ditautkan ke versi yang lebih lama secara otomatis ketika dikompilasi dari sumber?

Saya curiga ini berkaitan dengan ldconfigtetapi saya tidak yakin bagaimana caranya.

tepang
sumber

Jawaban:

87

Binari sendiri tahu versi perpustakaan mana yang mereka andalkan, dan memintanya secara khusus. Anda dapat menggunakan ldduntuk menunjukkan dependensi; milikku lsadalah:

$ ldd /bin/ls
    linux-gate.so.1 =>  (0xb784e000)
    librt.so.1 => /lib/librt.so.1 (0xb782c000)
    libacl.so.1 => /lib/libacl.so.1 (0xb7824000)
    libc.so.6 => /lib/libc.so.6 (0xb76dc000)
    libpthread.so.0 => /lib/libpthread.so.0 (0xb76c3000)
    /lib/ld-linux.so.2 (0xb784f000)
    libattr.so.1 => /lib/libattr.so.1 (0xb76bd000)

Seperti yang Anda lihat, itu menunjuk ke misalnya libpthread.so.0, bukan hanya libpthread.so.


Alasan untuk tautan simbolik adalah untuk tautan tersebut. Ketika Anda ingin menautkan libpthread.sosecara langsung, Anda memberi gccbendera -lpthread, dan itu menambahkan libawalan dan .soakhiran secara otomatis. Anda tidak bisa mengatakannya untuk menambahkan pada .so.0akhiran, jadi tautan simbolik menunjuk ke versi terbaru dari lib untuk memudahkan itu

Michael Mrozek
sumber
Tanda sama dengan "= ls" seharusnya tidak ada. Cukup gunakan "ldd ls"
bmacnaughton
1
@ bmacnaughton Itu mungkin akan memberi Anda kesalahan karena lddmemerlukan path lengkap ke executable. =lsmelakukannya di zsh, tapi saya mengubahnya karena tidak semua orang menggunakan shell itu
Michael Mrozek
Menarik. Saya menjalankan bash di Ubuntu dan tampaknya berfungsi tanpa path lengkap. Terima kasih atas penjelasannya - Saya tidak menggunakan zsh.
bmacnaughton
60

Angka-angka di perpustakaan bersama adalah konvensi yang digunakan di Linux untuk mengidentifikasi API perpustakaan. Biasanya formatnya adalah:

libFOO.so.MAJOR.MINOR

Dan seperti yang Anda perhatikan biasanya ada tautan simbolis dari libFOO.so ke libFOO.so.MAJOR.MINOR. ldconfig bertanggung jawab untuk memperbarui tautan ini ke versi terbaru.

MAJOR biasanya bertambah ketika API berubah (titik masuk baru dihapus atau parameter atau tipe diubah). MINOR biasanya ditambahkan untuk rilis perbaikan bug atau ketika API baru diperkenalkan tanpa melanggar API yang ada.

Diskusi yang lebih luas dapat ditemukan di sini: Membedah perpustakaan bersama

miguel.de.icaza
sumber
Hai Miguel, terima kasih untuk itu, sayang sekali saya tidak dapat menerima dua jawaban karena itu melengkapi dengan baik di atas. +1 dari saya, tautan luar biasa juga, terima kasih lagi!
4
Itu hampir benar, tetapi sebenarnya libFOO.so.MAJOR.MINOR(jadi tidak pada akhirnya)
JonnyJD
6
Jawaban ini sangat salah . Pertama, angka yang Anda lihat tidak ada hubungannya dengan API, ini murni ABI. Kedua, konvensi di sini bukan SEM versi semantik seperti yang Anda jawab sarankan. Alih-alih itu adalah konvensi libtool yang memiliki properti pemetaan yang bagus ke nomor versi perpustakaan tunggal yang dapat dibandingkan oleh ld.so (lihat gnu.org/software/libtool/manual/html_node/… untuk informasi lebih lanjut)
NewbiZ
23

Pustaka bersama harus diversi versi sesuai dengan skema berikut:

blah.so.X.Y.Z

dimana

  • X = mundur rilis ABI tidak kompatibel
  • Y = rilis ABI yang kompatibel ke belakang
  • Z = Hanya perubahan internal - tidak ada perubahan pada ABI

Biasanya Anda hanya melihat digit pertama seperti hello.so.1karena digit pertama adalah satu-satunya hal yang diperlukan untuk mengidentifikasi "versi" perpustakaan karena semua digit lainnya kompatibel dengan mundur.

ldconfigmemelihara tabel perpustakaan apa yang tersedia bersama pada suatu sistem dan di mana jalur ke perpustakaan itu ada. Anda dapat memverifikasi ini dengan menjalankan:

ldconfig -p

Ketika sebuah paket dibangun untuk sesuatu seperti Red Hat, pustaka bersama yang dipanggil dalam biner akan dilihat dan ditambahkan sebagai dependensi paket pada waktu pembuatan RPM. Karena itu, ketika Anda pergi untuk menginstal paket, penginstal akan mencari apakah hello.so.1diinstal pada sistem dengan memeriksa atau tidak ldconfig.

Anda dapat melihat dependensi suatu paket dengan melakukan sesuatu seperti:

rpm -qpR hello.rpm

Sistem ini (tidak seperti Windows) memungkinkan beberapa versi hello.sodiinstal pada suatu sistem dan digunakan oleh aplikasi yang berbeda secara bersamaan.

ascotan
sumber
Saya pikir ini adalah jawaban terbaik.
Kemin Zhou
1
Pustaka bersama harus versi menurut skema berikut (...) - Bisakah Anda memberikan referensi untuk pernyataan ini?
Piotr Dobrogost
19

libNAME.so adalah nama file yang digunakan oleh compiler / linker ketika pertama kali mencari perpustakaan yang ditentukan oleh -lNAME. Di dalam file perpustakaan bersama adalah bidang yang disebut SONAME. Bidang ini disetel saat pustaka itu sendiri pertama kali ditautkan ke objek bersama (jadi) oleh proses pembuatan. SONAME ini sebenarnya yang disimpan oleh tautan di dalam executable tergantung pada objek yang dibagikan yang dikaitkan dengannya. Biasanya SONAME adalah dalam bentuk libNAME.so.MAJOR dan diubah kapan saja perpustakaan menjadi tidak kompatibel dengan executable yang ada yang terhubung dengannya dan kedua versi utama perpustakaan dapat tetap diinstal sesuai kebutuhan (meskipun hanya satu yang akan diarahkan untuk pengembangan sebagai libNAME.so) Juga, untuk mendukung peningkatan yang mudah di antara versi kecil dari sebuah perpustakaan, libNAME.so.MAJOR biasanya merupakan tautan ke file seperti libNAME.so.MAJOR.MINOR. Versi minor baru dapat diinstal dan setelah selesai, tautan ke versi minor lama dihancurkan untuk menunjuk ke versi minor baru yang segera memutakhirkan semua eksekusi baru untuk menggunakan pustaka yang ditingkatkan. Juga, lihat jawaban saya untukLinux, GNU GCC, ld, skrip versi dan format biner ELF - Bagaimana cara kerjanya?

penguin359
sumber