Bagaimana ukuran tumpukan dan tumpukan dibatasi oleh OS?

21

Catatan : jika Anda perlu mempertimbangkan OS tertentu untuk dapat menjawab, silakan pertimbangkan Linux.

Setiap kali saya menjalankan suatu program, itu akan diberi ruang memori virtual untuk dijalankan, dengan area untuk tumpukannya dan satu untuk tumpukannya.

Pertanyaan 1 : apakah tumpukan dan tumpukan memiliki batas ukuran statis (misalnya, masing-masing 2 gigabytes), atau apakah batas ini dinamis, berubah sesuai dengan alokasi memori selama pelaksanaan program (yaitu, total 4 gigabyte yang akan digunakan oleh keduanya, jadi jika suatu program hanya menggunakan stack, ia akan dapat memiliki stack dengan 4 gigabytes)?

Pertanyaan 2 : Bagaimana batasannya? Apakah total memori RAM yang tersedia?

Pertanyaan 3 : Bagaimana dengan bagian teks (kode) dan data, bagaimana mereka dibatasi?

Daniel Scocco
sumber
Stack: unix.stackexchange.com/questions/145557/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Jawaban:

23

Ada dua batas memori yang berbeda. Batas memori virtual dan batas memori fisik.

Memori Virtual

Memori virtual dibatasi oleh ukuran dan tata letak ruang alamat yang tersedia. Biasanya pada awalnya adalah kode yang dapat dieksekusi dan data statis dan masa lalu yang menumpuk heap, sementara pada akhirnya adalah area yang dicadangkan oleh kernel, sebelum itu shared library dan stack (yang pada kebanyakan platform tumbuh ke bawah). Itu memberi heap dan stack ruang kosong untuk tumbuh, area lainnya dikenal saat proses startup dan diperbaiki.

Memori virtual bebas pada awalnya tidak ditandai sebagai dapat digunakan, tetapi ditandai seperti itu selama alokasi. Meskipun tumpukan dapat tumbuh ke semua memori yang tersedia, sebagian besar sistem tidak menumbuhkan tumpukan secara otomatis. Batas standar IIRC untuk stack adalah 8MiB di Linux dan 1MiB di Windows dan dapat diubah di kedua sistem. Memori virtual juga berisi file dan perangkat keras yang dipetakan memori.

Salah satu alasan mengapa stack tidak dapat dikembangkan secara otomatis (sewenang-wenang) adalah bahwa program multi-threaded membutuhkan stack yang terpisah untuk setiap utas, sehingga pada akhirnya mereka akan saling menghalangi.

Pada platform 32-bit, jumlah total memori virtual adalah 4GiB, baik Linux maupun Windows biasanya memesan 1GiB terakhir untuk kernel, memberikan Anda ruang alamat 3GiB paling banyak. Ada versi khusus Linux yang tidak memesan apa pun yang memberi Anda 4GiB penuh. Ini berguna untuk kasus yang jarang dari database besar di mana 1GiB terakhir menghemat hari, tetapi untuk penggunaan reguler sedikit lebih lambat karena reload tabel tabel tambahan.

Pada platform 64-bit memori virtual adalah 64EiB dan Anda tidak perlu memikirkannya.

Ingatan fisik

Memori fisik biasanya hanya dialokasikan oleh sistem operasi ketika proses perlu mengaksesnya. Berapa banyak memori fisik yang digunakan suatu proses adalah angka yang sangat kabur, karena sebagian memori dibagi antara proses (kode, pustaka bersama, dan file yang dipetakan lainnya), data dari file dimuat ke dalam memori sesuai permintaan dan dibuang ketika ada kekurangan memori dan Memori "anonim" (memori yang tidak didukung oleh file) dapat ditukar.

Di Linux apa yang terjadi ketika Anda kehabisan memori fisik tergantung pada vm.overcommit_memorypengaturan sistem. Defaultnya adalah overcommit. Ketika Anda meminta sistem untuk mengalokasikan memori, itu memberikan beberapa kepada Anda, tetapi hanya mengalokasikan memori virtual. Ketika Anda benar-benar mengakses memori, itu akan mencoba untuk mendapatkan beberapa memori fisik untuk digunakan, membuang data yang dapat dibaca ulang atau menukar hal-hal yang diperlukan. Jika ternyata tidak bisa membebaskan apa pun, itu hanya akan menghapus proses dari keberadaan (tidak ada cara untuk bereaksi, karena reaksi itu bisa memerlukan lebih banyak memori dan itu akan menyebabkan loop tanpa akhir).

Ini adalah bagaimana proses mati di Android (yang juga Linux). Logika ditingkatkan dengan logika proses mana untuk menghapus dari keberadaan berdasarkan pada apa proses itu lakukan dan berapa umurnya. Daripada proses android hanya berhenti melakukan apa pun, tetapi duduk di latar belakang dan "out of memory killer" akan membunuh mereka ketika membutuhkan memori untuk yang baru.

Jan Hudec
sumber
9

Saya pikir lebih mudah untuk menjawab ini dengan urutan bagaimana memori digunakan.

Pertanyaan 3: Bagaimana dengan bagian teks (kode) dan data, bagaimana mereka dibatasi? Teks dan Data disiapkan oleh kompiler. Persyaratan untuk kompiler adalah memastikan bahwa mereka dapat diakses dan mengemasnya di bagian bawah ruang alamat. Ruang alamat yang dapat diakses akan dibatasi oleh perangkat keras, misalnya jika register penunjuk instruksi adalah 32-bit, maka ruang alamat teks akan menjadi 4 GiB.

Pertanyaan 2: Bagaimana batasannya? Apakah total memori RAM yang tersedia? Setelah teks dan data, area di atas itu adalah heap. Dengan memori virtual, tumpukan praktis dapat tumbuh sampai dekat dengan ruang alamat max.

Pertanyaan 1: apakah tumpukan dan tumpukan memiliki batas ukuran statis (misalnya, masing-masing 2 gigabytes), atau apakah batas ini dinamis, berubah sesuai dengan alokasi memori selama pelaksanaan program (yaitu, total 4 gigabyte yang akan digunakan oleh keduanya, jadi jika suatu program hanya menggunakan stack, ia akan dapat memiliki stack dengan 4 gigabytes)? Segmen terakhir dalam ruang alamat proses adalah tumpukan. Tumpukan mengambil segmen ujung dari ruang alamat dan itu dimulai dari ujung dan tumbuh turun .

Karena tumpukan tumbuh dan tumpukan tumbuh, mereka pada dasarnya saling membatasi. Juga, karena kedua jenis segmen tersebut dapat ditulisi, itu tidak selalu merupakan pelanggaran bagi salah satu dari mereka untuk melewati batas, sehingga Anda dapat memiliki buffer atau stack overflow. Sekarang ada mekanisme untuk menghentikannya.

Ada batas yang ditetapkan untuk tumpukan (stack) untuk setiap proses untuk memulai. Batas ini dapat diubah saat runtime (menggunakan brk () / sbrk ()). Pada dasarnya apa yang terjadi adalah ketika proses membutuhkan lebih banyak ruang tumpukan dan telah kehabisan ruang yang dialokasikan, perpustakaan standar akan mengeluarkan panggilan ke OS. OS akan mengalokasikan halaman, yang biasanya akan dikelola oleh perpustakaan pengguna untuk digunakan oleh program. Yaitu jika program ingin 1 KiB, OS akan memberikan tambahan 4 KiB dan perpustakaan akan memberikan 1 KiB untuk program dan memiliki 3 KiB tersisa untuk digunakan ketika program meminta lebih banyak waktu berikutnya.

Sebagian besar waktu tata letak akan menjadi Teks, Data, Heap (tumbuh), ruang yang tidak terisi dan akhirnya Stack (tumbuh turun). Mereka semua berbagi ruang alamat yang sama.

imel96
sumber