GNU/Linux >> Belajar Linux >  >> Linux

Bagaimana cara kerja alokasi tumpukan di Linux?

Tampaknya batas memori tumpukan tidak dialokasikan (toh, tidak bisa dengan tumpukan tidak terbatas). https://www.kernel.org/doc/Documentation/vm/overcommit-accounting berkata:

Pertumbuhan tumpukan bahasa C melakukan mremap implisit. Jika Anda menginginkan jaminan mutlak dan berlari mendekati tepi, Anda HARUS memetakan tumpukan Anda untuk ukuran terbesar yang menurut Anda akan Anda perlukan. Untuk penggunaan tumpukan biasa, ini tidak terlalu menjadi masalah, tetapi ini adalah kasus sudut jika Anda benar-benar peduli

Namun memetakan tumpukan akan menjadi tujuan kompiler (jika ada opsi untuk itu).

EDIT:Setelah beberapa pengujian pada mesin Debian x84_64, saya menemukan bahwa tumpukan tumbuh tanpa panggilan sistem apa pun (menurut strace ). Jadi, ini berarti kernel menumbuhkannya secara otomatis (inilah arti "implisit" di atas), yaitu tanpa mmap eksplisit /mremap dari proses.

Cukup sulit untuk menemukan informasi rinci yang mengkonfirmasi hal ini. Saya merekomendasikan Memahami Manajer Memori Virtual Linux oleh Mel Gorman. Saya kira jawabannya ada di Bagian 4.6.1 Menangani Kesalahan Halaman , dengan pengecualian "Wilayah tidak valid tetapi berada di samping wilayah yang dapat diperluas seperti tumpukan" dan tindakan terkait "Perluas wilayah dan alokasikan halaman". Lihat juga D.5.2 Memperluas Tumpukan .

Referensi lain tentang manajemen memori Linux (tetapi hampir tidak ada tentang tumpukan):

  • FAQ Memori
  • Yang harus diketahui setiap pemrogram tentang memori oleh Ulrich Drepper

EDIT 2:Implementasi ini memiliki kelemahan:dalam kasus sudut, tabrakan tumpukan-tumpukan mungkin tidak terdeteksi, bahkan dalam kasus di mana tumpukan akan lebih besar dari batas! Alasannya adalah bahwa penulisan dalam variabel di tumpukan mungkin berakhir di memori tumpukan yang dialokasikan, dalam hal ini tidak ada kesalahan halaman dan kernel tidak dapat mengetahui bahwa tumpukan perlu diperpanjang. Lihat contoh saya di diskusi Tabrakan tumpukan-tumpukan senyap di bawah GNU/Linux yang saya mulai di daftar bantuan gcc. Untuk menghindarinya, kompiler perlu menambahkan beberapa kode pada pemanggilan fungsi; ini dapat dilakukan dengan -fstack-check untuk GCC (lihat balasan Ian Lance Taylor dan halaman manual GCC untuk detailnya).


Linux kernel 4.2

  • mm/mmap.c#acct_stack_growth memutuskan apakah akan segfault atau tidak. Ini menggunakan rlim[RLIMIT_STACK] yang sesuai dengan POSIX gerlimit(RLIMIT_STACK)
  • arch/x86/mm/fault.c#do_page_fault adalah penangan interupsi yang memulai rangkaian yang akhirnya memanggil acct_stack_growth
  • arch/x86/entry/entry_64.S menyiapkan penangan kesalahan halaman. Anda perlu tahu sedikit tentang paging untuk memahami bagian itu:Bagaimana cara kerja paging x86? | Stack Overflow

Program uji minimal

Kami kemudian dapat mengujinya dengan program NASM 64-bit minimal:

global _start
_start:
    sub rsp, 0x7FF000
    mov [rsp], rax
    mov rax, 60
    mov rdi, 0
    syscall

Pastikan Anda menonaktifkan ASLR dan menghapus variabel lingkungan karena akan masuk ke tumpukan dan menghabiskan ruang:

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
env -i ./main.out

Batasnya sedikit di bawah ulimit -s saya (8MiB untuk saya). Sepertinya ini karena data tambahan yang ditentukan System V awalnya diletakkan di tumpukan selain lingkungan:parameter baris perintah Linux 64 di Assembly | Stack Overflow

Jika Anda serius tentang ini, TODO membuat gambar initrd minimal yang mulai menulis dari tumpukan paling atas dan turun, lalu menjalankannya dengan QEMU + GDB. Letakkan dprintf pada loop mencetak alamat stack, dan breakpoint di acct_stack_growth . Itu akan menjadi mulia.

Terkait:

  • https://softwareengineering.stackexchange.com/questions/207386/how-are-the-size-of-the-stack-and-heap-limited-by-the-os
  • Dari mana memori tumpukan dialokasikan untuk proses Linux? | Stack Overflow
  • Apa yang dimaksud dengan Tumpukan Linux? | Stack Overflow
  • Berapa kedalaman rekursi maksimum di Python, dan bagaimana cara meningkatkannya? di Stack Overflow

Secara default, ukuran tumpukan maksimal dikonfigurasi menjadi 8MB per proses,
tetapi dapat diubah menggunakan ulimit :

Menampilkan default di kB:

$ ulimit -s
8192

Setel ke tidak terbatas:

ulimit -s unlimited

mempengaruhi shell dan subkulit saat ini dan proses anaknya.
(ulimit adalah perintah bawaan Shell)

Anda dapat menampilkan rentang alamat tumpukan aktual yang digunakan dengan:
cat /proc/$PID/maps | grep -F '[stack]'
di Linux.


Linux
  1. Apa itu NGINX? Bagaimana cara kerjanya?

  2. Cara Menghapus Cache Memori di Linux

  3. Bagaimana Cara Kerja Awk ‘!a[$0]++’?

  1. Bagaimana Cara Kerja Sticky Bit?

  2. Ssh – Bagaimana Tcp-keepalive Bekerja Di Ssh?

  3. Bagaimana cara kerja perintah 'ls' di Linux/Unix?

  1. Linux – Bagaimana Load Average Bekerja Dengan CPU Modern?

  2. Apakah alokasi memori di linux tidak memblokir?

  3. ZFS di Linux, apakah itu berfungsi?