GNU/Linux >> Belajar Linux >  >> Linux

Bagaimana menangani perpustakaan dinamis dan statis di Linux

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:

  1. Jalur relatif atau absolut dalam aplikasi (di-hardcode dengan -rpath opsi kompiler di GCC)
  2. Dalam variabel lingkungan LD_LIBRARY_PATH
  3. 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 ulang ld.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.


Linux
  1. Cara Mengatur Alamat IP Statis dan Konfigurasi Jaringan di Linux

  2. Cara Mengelola Inventaris Host Statis dan Dinamis yang Mungkin

  3. Cara Menginstal Dan Menggunakan Flatpak Di Linux

  1. Cara Mengelola dan Mendaftar Layanan di Linux

  2. Cara Menginstal dan Menguji Ansible di Linux

  3. Cara menyiapkan header dan pustaka untuk pengembangan Linux

  1. Cara dual-boot Linux dan Windows

  2. Cara Mengatur Alamat IP Statis dan Memodifikasi Tabel Perutean di Linux

  3. Cara Mengkonfigurasi Alamat IP Statis Dan Dinamis Di Arch Linux