GNU/Linux >> Belajar Linux >  >> Linux

Cara memeriksa ukuran heap untuk suatu proses di Linux

Saya pikir masalah awal Anda adalah malloc itu gagal mengalokasikan memori yang diminta pada sistem Anda.

Mengapa ini terjadi khusus untuk sistem Anda.

Ketika suatu proses dimuat, itu dialokasikan memori hingga alamat tertentu yang merupakan titik istirahat sistem untuk proses tersebut. Di luar alamat itu, memori tidak dipetakan untuk proses tersebut. Jadi ketika proses "mencapai" titik "break" itu meminta lebih banyak memori dari sistem dan salah satu cara untuk melakukannya adalah melalui system call sbrk
malloc akan melakukannya di bawah tenda tetapi di sistem Anda untuk beberapa alasan gagal.

Mungkin ada banyak alasan untuk ini misalnya:
1) Saya pikir di Linux ada batasan untuk ukuran memori maksimal. Saya pikir itu adalah ulimit dan mungkin Anda menekan itu. Periksa apakah sudah diatur ke batas
2) Mungkin sistem Anda terlalu dimuat
3) Program Anda melakukan manajemen memori yang buruk dan Anda berakhir dengan memori yang terfragmentasi jadi malloc tidak bisa mendapatkan ukuran potongan yang Anda minta.
4) Program Anda merusak malloc struktur data internal yaitu penggunaan pointer yang buruk
dll


Tumpukan biasanya sebesar memori virtual yang dapat dialamatkan pada arsitektur Anda.

Anda harus memeriksa batas sistem Anda saat ini dengan ulimit -a perintah dan cari baris ini max memory size (kbytes, -m) 3008828 , baris ini di OpenSuse 11.4 x86_64 saya dengan ram ~3,5 GiB mengatakan bahwa saya memiliki kira-kira 3 GB ram per proses.

Kemudian Anda benar-benar dapat menguji sistem Anda menggunakan program sederhana ini untuk memeriksa memori maksimum yang dapat digunakan per proses:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc,char* argv[]){
        size_t oneHundredMiB=100*1048576;
        size_t maxMemMiB=0;
        void *memPointer = NULL;
        do{
                if(memPointer != NULL){
                        printf("Max Tested Memory = %zi\n",maxMemMiB);
                        memset(memPointer,0,maxMemMiB);
                        free(memPointer);
                }
                maxMemMiB+=oneHundredMiB;
                memPointer=malloc(maxMemMiB);
        }while(memPointer != NULL);
        printf("Max Usable Memory aprox = %zi\n",maxMemMiB-oneHundredMiB);
        return 0;
}

Program ini mendapatkan memori dengan peningkatan 100MiB, menyajikan memori yang dialokasikan saat ini, mengalokasikan 0 di atasnya, lalu membebaskan memori. Ketika sistem tidak dapat memberikan lebih banyak memori, kembalikan NULL dan ini menampilkan jumlah ram terakhir yang dapat digunakan.

Peringatannya adalah bahwa sistem Anda akan mulai banyak menukar memori pada tahap akhir. Bergantung pada konfigurasi sistem Anda, kernel mungkin memutuskan untuk mematikan beberapa proses. Saya menggunakan peningkatan 100 MiB sehingga ada ruang bernapas untuk beberapa aplikasi dan sistem. Anda harus menutup semua yang tidak ingin Anda hancurkan.

Yang telah dibilang. Di sistem saya tempat saya menulis ini, tidak ada yang macet. Dan program di atas melaporkan hampir sama dengan ulimit -a . Perbedaannya adalah bahwa ini benar-benar menguji memori dan melalui memset() mengonfirmasi bahwa memori telah diberikan dan digunakan.

Sebagai perbandingan pada Ubuntu 10.04x86 VM dengan ram 256 MiB dan swap 400MiB, laporan ulimit adalah memory size (kbytes, -m) unlimited dan program kecil saya melaporkan 524.288.000 byte, yang kira-kira merupakan gabungan ram dan swap, mendiskon ram yang digunakan oleh perangkat lunak lain dan kernel.

Sunting:Seperti yang ditulis Adam Zalcman, ulimit -m tidak lagi dihormati pada kernel linux 2.6 dan lebih baru, jadi saya berdiri dikoreksi. Tapi ulimit -v dihormati. Untuk hasil praktis, Anda harus mengganti -m dengan -v, dan mencari virtual memory (kbytes, -v) 4515440 . Tampaknya hanya kebetulan bahwa kotak suse saya memiliki nilai -m yang bertepatan dengan apa yang dilaporkan oleh utilitas kecil saya. Anda harus ingat bahwa ini adalah memori virtual yang diberikan oleh kernel, jika ram fisik tidak mencukupi maka akan membutuhkan ruang swap untuk menggantikannya.

Jika Anda ingin mengetahui berapa banyak ram fisik yang tersedia tanpa mengganggu proses atau sistem apa pun, Anda dapat menggunakan

long total_available_ram =sysconf(_SC_AVPHYS_PAGES) * sysconf(_SC_PAGESIZE) ;

ini akan mengecualikan memori cache dan buffer, sehingga jumlah ini bisa jauh lebih kecil dari memori yang tersedia sebenarnya. Cache OS bisa sangat besar dan penggusurannya dapat memberikan memori tambahan yang diperlukan, tetapi itu ditangani oleh kernel.


Manajemen heap dan memori adalah fasilitas yang disediakan oleh pustaka C Anda (kemungkinan besar glibc). Itu memelihara tumpukan dan mengembalikan potongan memori kepada Anda setiap kali Anda melakukan malloc() . Ia tidak mengetahui batas ukuran heap:setiap kali Anda meminta lebih banyak memori daripada yang tersedia di heap, ia hanya pergi dan meminta kernel lebih banyak (baik menggunakan sbrk() atau mmap() ).

Secara default, kernel hampir selalu memberi Anda lebih banyak memori saat diminta. Artinya malloc() akan selalu mengembalikan alamat yang valid. Hanya ketika Anda merujuk ke halaman yang dialokasikan untuk pertama kalinya, kernel akan benar-benar repot menemukan halaman untuk Anda. Jika ternyata tidak dapat memberikannya kepada Anda, ia menjalankan pembunuh OOM yang menurut ukuran tertentu disebut kejahatan (yang mencakup ukuran memori virtual proses dan turunannya, level bagus, waktu berjalan keseluruhan, dll.) memilih korban dan mengirimkannya SIGTERM . Teknik manajemen memori ini disebut overcommit dan digunakan oleh kernel saat /proc/sys/vm/overcommit_memory adalah 0 atau 1. Lihat overcommit-accounting di dokumentasi kernel untuk detailnya.

Dengan menuliskan 2 ke dalam /proc/sys/vm/overcommit_memory Anda dapat menonaktifkan overcommit. Jika Anda melakukannya, kernel akan benar-benar memeriksa apakah ia memiliki memori sebelum menjanjikannya. Ini akan menghasilkan malloc() mengembalikan NULL jika tidak ada lagi memori yang tersedia.

Anda juga dapat menetapkan batas memori virtual yang dapat dialokasikan oleh proses dengan setrlimit() dan RLIMIT_AS atau dengan ulimit -v memerintah. Terlepas dari pengaturan overcommit yang dijelaskan di atas, jika proses mencoba mengalokasikan lebih banyak memori daripada batas, kernel akan menolaknya dan malloc() akan mengembalikan NULL. Perhatikan daripada di kernel Linux modern (termasuk seluruh seri 2.6.x) batas ukuran penduduk (setrlimit() dengan RLIMIT_RSS atau ulimit -m perintah) tidak efektif.

Sesi di bawah dijalankan pada kernel 2.6.32 dengan RAM 4GB dan swap 8GB.

$ cat bigmem.c
#include <stdlib.h>
#include <stdio.h>

int main() {
  int i = 0;
  for (; i < 13*1024; i++) {
    void* p = malloc(1024*1024);
    if (p == NULL) {
      fprintf(stderr, "malloc() returned NULL on %dth request\n", i);
      return 1;
    }
  }
  printf("Allocated it all\n");
  return 0;
}
$ cc -o bigmem bigmem.c
$ cat /proc/sys/vm/overcommit_memory
0
$ ./bigmem
Allocated it all
$ sudo bash -c "echo 2 > /proc/sys/vm/overcommit_memory"
$ cat /proc/sys/vm/overcommit_memory
2
$ ./bigmem
malloc() returned NULL on 8519th request
$ sudo bash -c "echo 0 > /proc/sys/vm/overcommit_memory"
$ cat /proc/sys/vm/overcommit_memory
0
$ ./bigmem
Allocated it all
$ ulimit -v $(( 1024*1024 ))
$ ./bigmem
malloc() returned NULL on 1026th request
$

Dalam contoh di atas, pertukaran atau OOM kill tidak akan pernah terjadi, tetapi ini akan berubah secara signifikan jika proses benar-benar mencoba menyentuh semua memori yang dialokasikan.

Untuk menjawab pertanyaan Anda secara langsung:kecuali Anda memiliki batas memori virtual yang ditetapkan secara eksplisit dengan ulimit -v perintah, tidak ada batas ukuran tumpukan selain sumber daya fisik mesin atau batas logis ruang alamat Anda (relevan dalam sistem 32-bit). glibc Anda akan terus mengalokasikan memori di heap dan akan meminta lebih banyak lagi dari kernel saat heap Anda tumbuh. Pada akhirnya Anda mungkin akan bertukar dengan buruk jika semua memori fisik habis. Setelah ruang swap habis, proses acak akan dimatikan oleh pembunuh OOM kernel.

Namun perhatikan, bahwa alokasi memori mungkin gagal karena lebih banyak alasan daripada kurangnya memori bebas, fragmentasi, atau mencapai batas yang dikonfigurasi. sbrk() dan mmap() panggilan yang digunakan oleh pengalokasi glib memiliki kegagalannya sendiri, mis. jeda program mencapai alamat lain yang sudah dialokasikan (misalnya memori bersama atau halaman yang sebelumnya dipetakan dengan mmap() ) atau jumlah maksimum pemetaan memori proses telah terlampaui.


Linux
  1. Cara Memeriksa Apakah Sistem Linux 32 bit Atau 64 Bit

  2. Linux – Batasi Penggunaan Memori Untuk Proses Linux Tunggal?

  3. Linux – Bagaimana Cara Berhenti Berbagi Jaringan Untuk Proses Saat Ini?

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

  2. cara memeriksa ukuran tumpukan yang dialokasikan untuk jvm oleh linux

  3. Bagaimana penggunaan memori dilaporkan di Linux?

  1. Cara Memeriksa Penggunaan Memori Proses dengan Perintah pmap Linux

  2. Cara memeriksa Versi OS dan Linux

  3. Cara Memeriksa Ukuran Ram di Baris Perintah Linux di Gb