GNU/Linux >> Belajar Linux >  >> Linux

Memuat Pustaka Bersama Dan Penggunaan Ram?

Saya bertanya-tanya tentang cara Linux mengelola perpustakaan bersama. (sebenarnya saya sedang membicarakan Maemo Fremantle, distro berbasis Debian yang dirilis pada tahun 2009 dengan RAM 256MB).

Mari kita asumsikan kita memiliki dua executable yang terhubung ke libQtCore.so.4 dan menggunakan simbolnya (menggunakan kelas dan fungsinya). Demi kesederhanaan, sebut saja mereka a dan b . Kami berasumsi bahwa kedua executable tertaut ke library yang sama.

Pertama kita luncurkan a . Perpustakaan harus dimuat. Apakah itu dimuat secara keseluruhan atau dimuat ke memori hanya di bagian yang diperlukan (karena kami tidak menggunakan setiap kelas, hanya kode tentang kelas yang digunakan yang dimuat)?

Kemudian kami meluncurkan b . Kami berasumsi bahwa a masih berjalan. b menautkan ke libQtCore.so.4 juga dan menggunakan beberapa kelas yang a digunakan, tetapi juga beberapa yang tidak digunakan oleh a . Apakah perpustakaan akan dimuat ganda (secara terpisah untuk a dan secara terpisah untuk b )? Atau apakah mereka akan menggunakan objek yang sama yang sudah ada di RAM. Jika b tidak menggunakan simbol baru dan a sudah berjalan apakah RAM yang digunakan oleh shared library bertambah? (Atau akankah perbedaannya tidak signifikan)

Jawaban yang Diterima:

CATATAN:Saya akan berasumsi bahwa mesin Anda memiliki unit pemetaan memori (MMU). Ada versi Linux (µClinux) yang tidak memerlukan MMU, dan jawaban ini tidak berlaku di sana.

Apa itu MMU? Ini adalah perangkat keras—bagian dari prosesor dan/atau pengontrol memori. Memahami penautan pustaka bersama tidak mengharuskan Anda untuk memahami dengan tepat cara kerja MMU, hanya saja MMU memungkinkan adanya perbedaan antara logis alamat memori (yang digunakan oleh program) dan fisik alamat memori (yang benar-benar ada di bus memori). Memori dipecah menjadi beberapa halaman, biasanya berukuran 4K di Linux. Dengan halaman 4k, alamat logis 0–4095 adalah halaman 0, alamat logis 4096–8191 adalah halaman 1, dll. MMU memetakannya ke halaman fisik RAM, dan setiap halaman logis biasanya dapat dipetakan ke 0 atau 1 halaman fisik. Halaman fisik yang diberikan dapat berhubungan dengan beberapa halaman logis (ini adalah bagaimana memori dibagi:beberapa halaman logis sesuai dengan halaman fisik yang sama). Catatan ini berlaku terlepas dari OS; ini adalah deskripsi perangkat kerasnya.

Pada sakelar proses, kernel mengubah pemetaan halaman MMU, sehingga setiap proses memiliki ruangnya sendiri. Alamat 4096 dalam proses 1000 dapat (dan biasanya) benar-benar berbeda dari alamat 4096 dalam proses 1001.

Hampir setiap kali Anda melihat alamat, itu adalah alamat logis. Program ruang pengguna hampir tidak pernah berurusan dengan alamat fisik.

Sekarang, ada beberapa cara untuk membangun perpustakaan juga. Katakanlah sebuah program memanggil fungsi foo() di dalam perpustakaan. CPU tidak tahu apa-apa tentang simbol, atau panggilan fungsi—hanya tahu cara melompat ke alamat logis, dan mengeksekusi kode apa pun yang ditemukan di sana. Ada beberapa cara untuk melakukan ini (dan hal serupa berlaku ketika perpustakaan mengakses data globalnya sendiri, dll.):

  1. Ini bisa membuat kode keras beberapa alamat logis untuk memanggilnya. Ini mengharuskan perpustakaan selalu dimuat pada alamat logis yang sama persis. Jika dua perpustakaan memerlukan alamat yang sama, penautan dinamis gagal dan Anda tidak dapat meluncurkan program. Perpustakaan dapat memerlukan perpustakaan lain, jadi ini pada dasarnya mengharuskan setiap perpustakaan di sistem memiliki alamat logis yang unik. Ini sangat cepat, jika berhasil. (Beginilah cara a.out melakukan sesuatu, dan semacam pengaturan yang dilakukan pra-penautan).
  2. Alamat logika palsu dapat di-hard-code, dan memberi tahu penaut dinamis untuk mengedit alamat yang benar saat memuat pustaka. Ini membutuhkan sedikit waktu saat memuat perpustakaan, tetapi setelah itu menjadi sangat cepat.
  3. Itu bisa menambahkan lapisan tipuan:gunakan register CPU untuk menyimpan alamat logis tempat perpustakaan dimuat, dan kemudian akses semuanya sebagai offset dari register itu. Ini membebankan biaya kinerja pada setiap akses.
Terkait:Linux – cp kehilangan metadata file?

Hampir tidak ada yang menggunakan # 1 lagi, setidaknya tidak pada sistem tujuan umum. Menyimpan daftar alamat logis yang unik itu tidak mungkin dilakukan pada sistem 32-bit (tidak cukup untuk digunakan) dan mimpi buruk administratif pada sistem 64-bit. Namun, semacam pra-tautan melakukan ini, pada basis per sistem.

Apakah #2 atau #3 digunakan bergantung pada apakah pustaka dibuat dengan -fPIC GCC (posisi kode independen) pilihan. #2 tanpa, #3 dengan. Umumnya, perpustakaan dibangun dengan -fPIC , jadi #3 adalah apa yang terjadi.

Untuk detail selengkapnya, lihat Cara Menulis Pustaka Bersama (PDF) dari Ulrich Drepper.

Jadi, akhirnya, pertanyaan Anda bisa terjawab:

  1. Jika perpustakaan dibuat dengan -fPIC (seperti yang seharusnya terjadi), sebagian besar halaman persis sama untuk setiap proses yang memuatnya. Proses Anda a dan b mungkin memuat perpustakaan di alamat logis yang berbeda, tetapi itu akan mengarah ke halaman fisik yang sama:memori akan dibagikan. Selanjutnya, data dalam RAM sama persis dengan apa yang ada di disk, sehingga hanya dapat dimuat saat dibutuhkan oleh pengendali kesalahan halaman.
  2. Jika perpustakaan dibuat tanpa -fPIC , kemudian ternyata sebagian besar halaman perpustakaan akan membutuhkan pengeditan tautan, dan akan berbeda. Oleh karena itu, mereka harus menjadi halaman fisik yang terpisah (karena berisi data yang berbeda). Itu berarti mereka tidak dibagikan. Halaman tidak cocok dengan apa yang ada di disk, jadi saya tidak akan terkejut jika seluruh perpustakaan dimuat. Tentu saja selanjutnya dapat ditukar ke disk (di swapfile).

Anda dapat memeriksanya dengan pmap alat, atau langsung dengan memeriksa berbagai file di /proc . Sebagai contoh, berikut adalah output (sebagian) dari pmap -x pada dua bc baru yang berbeda yang muncul s. Perhatikan bahwa alamat yang ditunjukkan oleh pmap adalah, seperti biasa, alamat logis:

pmap -x 14739
Address           Kbytes     RSS   Dirty Mode  Mapping
00007f81803ac000     244     176       0 r-x-- libreadline.so.6.2
00007f81803e9000    2048       0       0 ----- libreadline.so.6.2
00007f81805e9000       8       8       8 r---- libreadline.so.6.2
00007f81805eb000      24      24      24 rw--- libreadline.so.6.2


pmap -x 17739
Address           Kbytes     RSS   Dirty Mode  Mapping
00007f784dc77000     244     176       0 r-x-- libreadline.so.6.2
00007f784dcb4000    2048       0       0 ----- libreadline.so.6.2
00007f784deb4000       8       8       8 r---- libreadline.so.6.2
00007f784deb6000      24      24      24 rw--- libreadline.so.6.2

Anda dapat melihat bahwa perpustakaan dimuat dalam beberapa bagian, dan pmap -x memberi Anda detail masing-masing secara terpisah. Anda akan melihat bahwa alamat logis berbeda antara kedua proses; Anda cukup mengharapkan mereka untuk menjadi sama (karena program yang sama berjalan, dan komputer biasanya dapat diprediksi seperti itu), tetapi ada fitur keamanan yang disebut pengacakan tata letak ruang alamat yang sengaja mengacaknya.

Anda dapat melihat dari perbedaan ukuran (Kbytes) dan ukuran penduduk (RSS) bahwa seluruh segmen perpustakaan belum dimuat. Terakhir, Anda dapat melihat bahwa untuk pemetaan yang lebih besar, dirty adalah 0, artinya sesuai dengan apa yang ada di disk.

Anda dapat menjalankan kembali dengan pmap -XX , dan itu akan menunjukkan kepada Anda—bergantung pada versi kernel yang Anda jalankan, karena -XX output bervariasi menurut versi kernel—bahwa pemetaan pertama memiliki Shared_Clean dari 176, yang sama persis dengan RSS . Shared memori berarti halaman fisik dibagi antara beberapa proses, dan karena cocok dengan RSS, itu berarti semua perpustakaan yang ada di memori dibagikan (lihat Lihat Juga di bawah untuk penjelasan lebih lanjut tentang berbagi vs. pribadi):

pmap -XX 17739
         Address Perm   Offset Device   Inode  Size  Rss Pss Shared_Clean Shared_Dirty Private_Clean Private_Dirty Referenced Anonymous AnonHugePages Swap KernelPageSize MMUPageSize Locked                   VmFlagsMapping
    7f784dc77000 r-xp 00000000  fd:00 1837043   244  176  19          176            0             0             0        176         0             0    0              4           4      0       rd ex mr mw me sd  libreadline.so.6.2
    7f784dcb4000 ---p 0003d000  fd:00 1837043  2048    0   0            0            0             0             0          0         0             0    0              4           4      0             mr mw me sd  libreadline.so.6.2
    7f784deb4000 r--p 0003d000  fd:00 1837043     8    8   8            0            0             0             8          8         8             0    0              4           4      0       rd mr mw me ac sd  libreadline.so.6.2
    7f784deb6000 rw-p 0003f000  fd:00 1837043    24   24  24            0            0             0            24         24        24             0    0              4           4      0    rd wr mr mw me ac sd  libreadline.so.6.2

Lihat Juga

  • Mendapatkan informasi tentang penggunaan memori suatu proses dari /proc/pid/smaps untuk penjelasan tentang hal bersih/kotor bersama/pribadi.
Terkait:Linux – Bagaimana cara menampilkan sar untuk hari sebelumnya?
Linux
  1. Mengukur Penggunaan Ram Suatu Program?

  2. Cara Memeriksa Ukuran Total RAM dan Penggunaan Memori di Linux

  3. Cara menginisialisasi perpustakaan bersama di Linux

  1. Mengupas perpustakaan bersama linux

  2. Bagaimana cara menyematkan informasi versi ke dalam pustaka bersama dan biner?

  3. libstdc++.so.5:tidak dapat membuka file objek bersama - tetapi pustaka diinstal dan mutakhir

  1. Perbedaan antara objek bersama (.so), pustaka statis (.a), dan DLL (.so)?

  2. Cara kerja penautan dinamis, penggunaannya, dan bagaimana dan mengapa Anda membuat dylib

  3. Bagaimana cara memeriksa apakah perpustakaan bersama diinstal?