Linux, di satu sisi, adalah serangkaian perpustakaan statis dan dinamis yang saling bergantung satu sama lain. Untuk pengguna baru sistem berbasis Linux, seluruh penanganan perpustakaan bisa menjadi misteri. Namun dengan pengalaman, sejumlah besar kode bersama yang dibangun ke dalam sistem operasi dapat menjadi keuntungan saat menulis aplikasi baru.
Untuk membantu Anda memahami topik ini, saya menyiapkan contoh aplikasi kecil yang menunjukkan metode paling umum yang bekerja pada distribusi Linux umum (ini belum diuji pada sistem lain). Untuk mengikuti tutorial langsung ini menggunakan aplikasi contoh, buka prompt perintah dan ketik:
$ git clone https://github.com/hANSIc99/library_sample
$ cd library_sample/
$ make
cc -c main.c -Wall -Werror
cc -c libmy_static_a.c -o libmy_static_a.o -Wall -Werror
cc -c libmy_static_b.c -o libmy_static_b.o -Wall -Werror
ar -rsv libmy_static.a libmy_static_a.o libmy_static_b.o
ar:membuat libmy_static.a
a - libmy_static_a.o
a - libmy_static_b.o
cc -c -fPIC libmy_shared.c -o libmy_shared.o
cc - shared -o libmy_shared.so libmy_shared.o
$ bersihkan
rm *.o
Setelah menjalankan perintah ini, file-file ini harus ditambahkan ke direktori (jalankan ls
untuk melihatnya):
aplikasi_saya
libmy_static.a
libmy_shared.so
Tentang penautan statis
Saat aplikasi Anda menautkan ke pustaka statis, kode pustaka menjadi bagian dari hasil yang dapat dieksekusi. Ini dilakukan hanya sekali pada waktu penautan, dan pustaka statis ini biasanya diakhiri dengan .a
ekstensi.
Pustaka statis adalah arsip (ar) dari file objek. File objek biasanya dalam format ELF. ELF adalah kependekan dari Executable and Linkable Format, yang kompatibel dengan banyak sistem operasi.
Keluaran dari file
perintah memberitahu Anda bahwa perpustakaan statis libmy_static.a
adalah ar
jenis arsip:
$ file libmy_static.a
libmy_static.a:arsip ar saat ini
Dengan ar -t
, Anda dapat melihat arsip ini; itu menunjukkan dua file objek:
$ ar -t libmy_static.a
libmy_static_a.o
libmy_static_b.o
Anda dapat mengekstrak file arsip dengan ar -x <archive-file>
. File yang diekstrak adalah file objek dalam format ELF:
$ ar -x libmy_static.a
$ file libmy_static_a.o
libmy_static_a.o:ELF 64-bit LSB relocatable, x86-64, versi 1 (SYSV), tidak dilucuti
Tentang penautan dinamis
Lebih banyak sumber daya Linux
- Lembar contekan perintah Linux
- Lembar contekan perintah Linux tingkat lanjut
- Kursus online gratis:Ikhtisar Teknis RHEL
- Lembar contekan jaringan Linux
- Lembar contekan SELinux
- Lembar contekan perintah umum Linux
- Apa itu container Linux?
- Artikel Linux terbaru kami
Penautan dinamis berarti penggunaan pustaka bersama. Pustaka bersama biasanya diakhiri dengan .so
(kependekan dari "objek bersama").
Pustaka bersama adalah cara paling umum untuk mengelola dependensi pada sistem Linux. Sumber daya bersama ini dimuat ke dalam memori sebelum aplikasi dimulai, dan ketika beberapa proses memerlukan pustaka yang sama, itu akan dimuat hanya sekali pada sistem. Fitur ini menghemat penggunaan memori oleh aplikasi.
Hal lain yang perlu diperhatikan adalah ketika bug diperbaiki di pustaka bersama, setiap aplikasi yang mereferensikan pustaka ini akan mendapat untung darinya. Ini juga berarti bahwa jika bug tetap tidak terdeteksi, setiap aplikasi referensi akan mengalaminya (jika aplikasi menggunakan bagian yang terpengaruh).
Ini bisa sangat sulit bagi pemula ketika aplikasi memerlukan versi perpustakaan tertentu, tetapi penaut hanya mengetahui lokasi versi yang tidak kompatibel. Dalam hal ini, Anda harus membantu penaut menemukan jalur ke versi yang benar.
Meskipun ini bukan masalah sehari-hari, memahami penautan dinamis pasti akan membantu Anda mengatasi masalah tersebut.
Untungnya, mekanisme untuk ini cukup mudah.
Untuk mendeteksi perpustakaan mana yang diperlukan untuk memulai aplikasi, Anda dapat menggunakan ldd
, yang akan mencetak pustaka bersama yang digunakan oleh file tertentu:
$ ldd my_app
linux-vdso.so.1 (0x00007ffd1299c000)
libmy_shared.so => tidak ditemukan
libc.so.6 => /lib64/libc.so.6 (0x00007f56b869b000)
/lib64/ld-linux-x86-64.so.2 (0x00007f56b8881000)
Perhatikan bahwa perpustakaan libmy_shared.so
adalah bagian dari repositori tetapi tidak ditemukan. Ini karena dynamic linker, yang bertanggung jawab untuk memuat semua dependensi ke dalam memori sebelum menjalankan aplikasi, tidak dapat menemukan library ini di lokasi standar yang dicarinya.
Kesalahan terkait dengan penaut yang menemukan versi pustaka umum yang tidak kompatibel (seperti bzip2
, misalnya) bisa sangat membingungkan bagi pengguna baru. Salah satu caranya adalah dengan menambahkan folder repositori ke variabel lingkungan LD_LIBRARY_PATH
untuk memberi tahu tautan di mana harus mencari versi yang benar. Dalam hal ini, versi yang tepat ada di folder ini, jadi Anda dapat mengekspornya:
$ LD_LIBRARY_PATH=$(pwd):$LD_LIBRARY_PATH
$ ekspor LD_LIBRARY_PATH
Sekarang tautan dinamis tahu di mana menemukan perpustakaan, dan aplikasi dapat dijalankan. Anda dapat menjalankan kembali ldd
untuk memanggil tautan dinamis, yang memeriksa dependensi aplikasi dan memuatnya ke dalam memori. Alamat memori ditampilkan setelah jalur objek:
$ ldd my_app
linux-vdso.so.1 (0x00007ffd385f7000)
libmy_shared.so => /home/stephan/library_sample/libmy_shared.so (0x00007f3fad401000) . /> 6 => /lib64/libc.so.6 (0x00007f3fad21d000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3fad408000)
Untuk mengetahui tautan mana yang dipanggil, Anda dapat menggunakan file
:
$ file my_app
my_app:ELF 64-bit LSB yang dapat dieksekusi, x86-64, versi 1 (SYSV), tertaut secara dinamis, juru bahasa /lib64/ld-linux-x86-64.so.2, BuildID[ sha1]=26c677b771122b4c99f0fd9ee001e6c743550fa6, untuk GNU/Linux 3.2.0, tidak dihapus
Penaut /lib64/ld-linux-x86–64.so.2
adalah tautan simbolis ke ld-2.30.so
, yang merupakan tautan default untuk distribusi Linux saya:
$ file /lib64/ld-linux-x86-64.so.2
/lib64/ld-linux-x86-64.so.2:tautan simbolis ke ld-2.31.so
Melihat kembali ke keluaran ldd
, Anda juga dapat melihat (di sebelah libmy_shared.so
) bahwa setiap ketergantungan diakhiri dengan angka (mis., /lib64/libc.so.6
). Skema penamaan objek bersama yang biasa adalah:
**lib** XYZ.so **.<MAJOR>** . **<MINOR>**
Di sistem saya, libc.so.6
juga merupakan tautan simbolis ke objek bersama libc-2.30.so
dalam folder yang sama:
$ file /lib64/libc.so.6
/lib64/libc.so.6:tautan simbolis ke libc-2.31.so
Jika Anda menghadapi masalah bahwa aplikasi tidak akan dimulai karena pustaka yang dimuat memiliki versi yang salah, kemungkinan besar Anda dapat memperbaiki masalah ini dengan memeriksa dan mengatur ulang tautan simbolis atau menentukan jalur pencarian yang benar (lihat "Pemuat dinamis :ld.so" di bawah).
Untuk informasi lebih lanjut, lihat ldd
halaman manual.
Pemuatan dinamis
Pemuatan dinamis berarti bahwa perpustakaan (mis., .so
file) dimuat selama runtime program. Ini dilakukan dengan menggunakan skema pemrograman tertentu.
Pemuatan dinamis diterapkan ketika aplikasi menggunakan plugin yang dapat dimodifikasi selama runtime.
Lihat dlopen
halaman manual untuk informasi lebih lanjut.
Pemuat dinamis:ld.so
Di Linux, Anda kebanyakan berurusan dengan objek bersama, jadi harus ada mekanisme yang mendeteksi dependensi aplikasi dan memuatnya ke dalam memori.
ld.so
mencari objek bersama di tempat-tempat ini dalam urutan berikut:
- Jalur relatif atau absolut dalam aplikasi (di-hardcode dengan
-rpath
opsi kompiler di GCC) - Dalam variabel lingkungan
LD_LIBRARY_PATH
- Dalam file
/etc/ld.so.cache
Ingatlah bahwa menambahkan perpustakaan ke arsip perpustakaan sistem /usr/lib64
membutuhkan hak administrator. Anda dapat menyalin libmy_shared.so
secara manual ke arsip perpustakaan dan buat aplikasi berfungsi tanpa menyetel LD_LIBRARY_PATH
:
unset LD_LIBRARY_PATH
sudo cp libmy_shared.so /usr/lib64/
Saat Anda menjalankan ldd
, Anda dapat melihat jalur ke arsip perpustakaan muncul sekarang:
$ ldd my_app
linux-vdso.so.1 (0x00007ffe82fab000)
libmy_shared.so => /lib64/libmy_shared.so (0x00007f0a963e0000)
=> libc. lib64/libc.so.6 (0x00007f0a96216000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0a96401000)
Sesuaikan perpustakaan bersama pada waktu kompilasi
Jika Anda ingin aplikasi Anda menggunakan pustaka bersama, Anda dapat menentukan jalur absolut atau relatif selama waktu kompilasi.
Ubah makefile (baris 10) dan kompilasi ulang program dengan menjalankan make -B
. Kemudian, output dari ldd
menunjukkan libmy_shared.so
terdaftar dengan jalur absolutnya.
Ubah ini:
CFLAGS =-Wall -Werror -Wl,-rpath,$(shell pwd)
Untuk ini (pastikan untuk mengedit nama pengguna):
CFLAGS =/home/stephan/library_sample/libmy_shared.so
Kemudian kompilasi ulang:
$ make
Konfirmasikan itu menggunakan jalur absolut yang Anda tetapkan, yang dapat Anda lihat di baris 2 dari output:
$ ldd my_app
linux-vdso.so.1 (0x00007ffe143ed000)
libmy_shared.so => /lib64/libmy_shared.so (0x00007fe50926d000)
/home/stephan/library .so (0x00007fe509268000)
libc.so.6 => /lib64/libc.so.6 (0x00007fe50909e000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe50928e000)Ini adalah contoh yang bagus, tetapi bagaimana cara kerjanya jika Anda membuat perpustakaan untuk digunakan orang lain? Lokasi perpustakaan baru dapat didaftarkan dengan menuliskannya ke
/etc/ld.so.conf
atau membuat<library-name>.conf
file yang berisi lokasi di bawah/etc/ld.so.conf.d/
. Setelah itu,ldconfig
harus dieksekusi untuk menulis ulangld.so.cache
mengajukan. Langkah ini terkadang diperlukan setelah Anda menginstal program yang membawa beberapa perpustakaan bersama khusus.Lihat
ld.so
halaman manual untuk informasi selengkapnya.Cara menangani banyak arsitektur
Biasanya, ada pustaka yang berbeda untuk aplikasi versi 32-bit dan 64-bit. Daftar berikut menunjukkan lokasi standarnya untuk distribusi Linux yang berbeda:
Keluarga Topi Merah
- 32 bit:
/usr/lib
- 64 bit:
/usr/lib64
Keluarga Debian
- 32 bit:
/usr/lib/i386-linux-gnu
- 64 bit:
/usr/lib/x86_64-linux-gnu
Keluarga Arch Linux
- 32 bit:
/usr/lib32
- 64 bit:
/usr/lib64
FreeBSD (teknis bukan distribusi Linux)
- 32bit:
/usr/lib32
- 64bit:
/usr/lib
Mengetahui di mana mencari perpustakaan utama ini dapat membuat tautan perpustakaan yang rusak menjadi masalah di masa lalu.
Meskipun mungkin membingungkan pada awalnya, memahami manajemen ketergantungan di perpustakaan Linux adalah cara untuk merasa mengendalikan sistem operasi. Jalankan langkah-langkah ini dengan aplikasi lain untuk memahami library umum, dan terus pelajari cara mengatasi masalah library yang mungkin muncul di sepanjang jalan Anda.