Bisakah Linux “kehabisan RAM”?

20

Saya melihat beberapa posting di web orang-orang yang kelihatannya mengeluhkan VPS yang di-host secara tidak sengaja membunuh proses karena mereka menggunakan terlalu banyak RAM.

Bagaimana ini mungkin? Saya pikir semua OS modern menyediakan "infinite RAM" dengan hanya menggunakan disk swap untuk apa pun yang melebihi RAM fisik. Apakah ini benar?

Apa yang mungkin terjadi jika suatu proses "mati karena RAM rendah"?

kaca
sumber
12
Tidak ada OS yang memiliki RAM tak terbatas . Selain chip RAM fisik dalam mesin, OS dapat - biasanya, secara opsional - menggunakan 'file swap' yang disebut pada disk. Ketika komputer membutuhkan lebih banyak memori daripada yang ada pada RAM stick, itu menukar beberapa hal ke file swap. Tetapi ketika file swap mencapai kapasitasnya - baik karena Anda menetapkan ukuran maksimum (khas) atau disk terisi - Anda kehabisan memori virtual.
John Dibling
@JohnDibling; jadi adakah alasan mengapa seseorang ingin membatasi ukuran swap selain untuk menghemat ruang disk untuk sistem file? Dengan kata lain jika saya memiliki disk 20GB dan hanya 1GB file, apakah ada alasan untuk tidak mengatur ukuran swap saya menjadi 19GB?
themirror
1
Untuk menyederhanakan hal-hal, saya akan mengatakan dua alasan untuk membatasi ukuran swap adalah 1) untuk mengurangi konsumsi disk dan 2) untuk meningkatkan kinerja. Yang terakhir mungkin lebih benar di bawah Windows daripada / * NIX, tetapi sekali lagi, jika Anda menggunakan ruang swap pada disk Anda, kinerja Anda menurun. Akses disk lebih lambat dari RAM, atau jauh lebih lambat dari RAM, tergantung pada sistem.
John Dibling
9
Swap bukan RAM . en.wikipedia.org/wiki/Random-access_memory Jumlah RAM di sistem Anda adalah jumlah RAM di sistem Anda - titik. Ini bukan volume yang ambigu atau dinamis. Ini benar-benar diperbaiki. "Memori" adalah konsep yang lebih ambigu, tetapi perbedaan antara RAM dan bentuk penyimpanan lainnya, seperti yang ditunjukkan terdon (+1), cukup signifikan. Disk swap tidak dapat menggantikan kinerja RAM dengan banyak pesanan . Suatu sistem yang sangat bergantung pada swap paling baik bersifat sementara dan secara umum: sampah.
goldilocks
1
Jadi ruang disk sekarang tidak terbatas?
Kaz

Jawaban:

41

Apa yang mungkin terjadi jika suatu proses "mati karena RAM rendah"?

Terkadang dikatakan bahwa linux secara default tidak pernah menolak permintaan untuk lebih banyak memori dari kode aplikasi - mis malloc(). 1 Ini sebenarnya tidak benar; default menggunakan heuristik dimana

Overcommits ruang alamat yang jelas ditolak. Digunakan untuk sistem tipikal. Ini memastikan alokasi liar yang serius gagal sementara memungkinkan terlalu banyak komitmen untuk mengurangi penggunaan swap.

Dari [linux_src]/Documentation/vm/overcommit-accounting(semua kutipan berasal dari pohon 3.11). Tepatnya apa yang dianggap sebagai "alokasi liar yang serius" tidak dibuat eksplisit, jadi kami harus melalui sumber untuk menentukan detailnya. Kita juga dapat menggunakan metode eksperimental pada catatan kaki 2 (di bawah) untuk mencoba dan mendapatkan beberapa refleksi heuristik - berdasarkan itu, pengamatan empiris awal saya adalah bahwa dalam keadaan ideal (== sistem idle), jika Anda tidak t memiliki swap apa pun, Anda akan diizinkan untuk mengalokasikan sekitar setengah RAM Anda, dan jika Anda memiliki swap, Anda akan mendapatkan sekitar setengah RAM Anda ditambah semua swap Anda. Itu lebih atau kurang per proses (tetapi perhatikan batas ini dinamis dan dapat berubah karena keadaan, lihat beberapa pengamatan di catatan kaki 5).

Setengah RAM Anda plus swap secara eksplisit merupakan standar untuk bidang "CommitLimit" di /proc/meminfo. Inilah artinya - dan perhatikan itu sebenarnya tidak ada hubungannya dengan batas yang baru saja didiskusikan (dari [src]/Documentation/filesystems/proc.txt):

CommitLimit: Berdasarkan rasio overcommit ('vm.overcommit_ratio'), ini adalah jumlah total memori yang saat ini tersedia untuk dialokasikan pada sistem. Batas ini hanya dipatuhi jika penghitungan overcommit ketat diaktifkan (mode 2 dalam 'vm.overcommit_memory'). CommitLimit dihitung dengan rumus berikut: CommitLimit = ('vm.overcommit_ratio' * RAM Fisik) + Swap Sebagai contoh, pada sistem dengan 1G RAM fisik dan 7G swap dengan 'vm.overcommit_ratio' dari 30 akan menghasilkan Batas Komisi 7,3G.

Doc-akuntansi overcommit yang dikutip sebelumnya menyatakan bahwa standarnya vm.overcommit_ratioadalah 50. Jadi jika Anda sysctl vm.overcommit_memory=2, Anda dapat menyesuaikan vm.covercommit_ratio (with sysctl) dan melihat konsekuensinya. 3 Mode default, ketika CommitLimittidak ditegakkan dan hanya "ruang alamat overcommits jelas ditolak", adalah ketika vm.overcommit_memory=0.

Sementara strategi default memang memiliki batas heuristik per-proses yang mencegah "alokasi liar yang serius", itu membuat sistem secara keseluruhan bebas untuk menjadi liar, alokasi yang bijak. 4 Ini berarti pada titik tertentu kehabisan memori dan harus menyatakan kebangkrutan untuk beberapa proses melalui pembunuh OOM .

Apa yang dibunuh pembunuh OOM? Belum tentu proses yang meminta memori ketika tidak ada, karena itu belum tentu proses yang benar-benar bersalah, dan yang lebih penting, belum tentu proses yang paling cepat akan mengeluarkan sistem dari masalah yang ada.

Ini dikutip dari sini yang mungkin mengutip sumber 2.6.x:

/*
 * oom_badness - calculate a numeric value for how bad this task has been
 *
 * The formula used is relatively simple and documented inline in the
 * function. The main rationale is that we want to select a good task
 * to kill when we run out of memory.
 *
 * Good in this context means that:
 * 1) we lose the minimum amount of work done
 * 2) we recover a large amount of memory
 * 3) we don't kill anything innocent of eating tons of memory
 * 4) we want to kill the minimum amount of processes (one)
 * 5) we try to kill the process the user expects us to kill, this
 *    algorithm has been meticulously tuned to meet the principle
 *    of least surprise ... (be careful when you change it)
 */

Yang sepertinya alasan yang layak. Namun, tanpa mendapatkan forensik, # 5 (yang berlebihan dari # 1) tampaknya seperti implementasi penjualan yang sulit, dan # 3 berlebihan dari # 2. Jadi mungkin masuk akal untuk mempertimbangkan penurunan ini ke # 2/3 dan # 4.

Saya memahami sebuah sumber baru-baru ini (3.11) dan memperhatikan bahwa komentar ini telah berubah untuk sementara:

/**
 * oom_badness - heuristic function to determine which candidate task to kill
 *
 * The heuristic for determining which task to kill is made to be as simple and
 * predictable as possible.  The goal is to return the highest value for the
 * task consuming the most memory to avoid subsequent oom failures.
 */

Ini sedikit lebih eksplisit tentang # 2: "Tujuannya adalah untuk [membunuh] tugas yang menghabiskan sebagian besar memori untuk menghindari kegagalan berikutnya," dan dengan implikasi # 4 ( "kami ingin membunuh jumlah minimum proses ( satu ) ) .

Jika Anda ingin melihat pembunuh OOM beraksi, lihat catatan kaki 5.


1 Khayalan Gilles untungnya membebaskan saya dari, lihat komentar.


2 Inilah sedikit C yang langsung yang meminta potongan memori yang semakin besar untuk menentukan kapan permintaan untuk lebih banyak akan gagal:

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

#define MB 1 << 20

int main (void) {
    uint64_t bytes = MB;
    void *p = malloc(bytes);
    while (p) {
        fprintf (stderr,
            "%lu kB allocated.\n",
            bytes / 1024
        );
        free(p);
        bytes += MB;
        p = malloc(bytes);
    }
    fprintf (stderr,
        "Failed at %lu kB.\n",
        bytes / 1024
    );
    return 0;
}            

Jika Anda tidak tahu C, Anda bisa mengkompilasi ini gcc virtlimitcheck.c -o virtlimitcheck, lalu jalankan ./virtlimitcheck. Ini benar-benar tidak berbahaya, karena prosesnya tidak menggunakan ruang yang diminta - yaitu, ia tidak pernah benar-benar menggunakan RAM apa pun.

Pada sistem 3.11 x86_64 dengan sistem 4 GB dan 6 GB swap, saya gagal pada ~ 7400000 kB; jumlahnya berfluktuasi, jadi mungkin keadaan adalah faktor. Ini kebetulan dekat dengan CommitLimitdi /proc/meminfo, tetapi memodifikasi ini melalui vm.overcommit_ratiotidak ada bedanya. Pada sistem 3.6M 32-bit ARM 448 MB dengan 64 MB swap, bagaimanapun, saya gagal ~ 230 MB. Ini menarik karena dalam kasus pertama jumlahnya hampir dua kali lipat jumlah RAM, sedangkan pada yang kedua adalah sekitar 1/4 itu - sangat menyiratkan jumlah swap adalah faktor. Ini dikonfirmasi dengan mematikan swap pada sistem pertama, ketika ambang kegagalan turun ke ~ 1,95 GB, rasio yang sangat mirip dengan kotak ARM kecil.

Tetapi apakah ini benar-benar per proses? Tampaknya begitu. Program singkat di bawah ini meminta sepotong memori yang ditentukan pengguna, dan jika berhasil, menunggu Anda untuk kembali - dengan cara ini Anda dapat mencoba beberapa contoh bersamaan:

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

#define MB 1 << 20

int main (int argc, const char *argv[]) {
    unsigned long int megabytes = strtoul(argv[1], NULL, 10);
    void *p = malloc(megabytes * MB);
    fprintf(stderr,"Allocating %lu MB...", megabytes);
    if (!p) fprintf(stderr,"fail.");
    else {
        fprintf(stderr,"success.");
        getchar();
        free(p);
    }
    return 0;
}

Berhati-hatilah, bagaimanapun, bahwa ini bukan semata-mata tentang jumlah RAM dan swap terlepas dari penggunaan - lihat catatan kaki 5 untuk pengamatan tentang efek dari status sistem.


3 CommitLimit mengacu pada jumlah ruang alamat yang diizinkan untuk sistem ketika vm.overcommit_memory = 2. Agaknya, jumlah yang dapat Anda alokasikan harus dikurangi dengan apa yang sudah dilakukan, yang tampaknya adalah Committed_ASbidang.

Eksperimen yang berpotensi menarik yang menunjukkan ini adalah untuk menambah #include <unistd.h>bagian atas virtlimitcheck.c (lihat catatan kaki 2), dan fork()tepat sebelum while()perulangan. Itu tidak dijamin berfungsi seperti yang dijelaskan di sini tanpa sinkronisasi yang melelahkan, tetapi ada kemungkinan yang layak, YMMV:

> sysctl vm.overcommit_memory=2
vm.overcommit_memory = 2
> cat /proc/meminfo | grep Commit
CommitLimit:     9231660 kB
Committed_AS:    3141440 kB
> ./virtlimitcheck 2&> tmp.txt
> cat tmp.txt | grep Failed
Failed at 3051520 kB.
Failed at 6099968 kB.

Ini masuk akal - melihat tmp.txt secara rinci Anda dapat melihat proses berganti alokasi yang lebih besar dan lebih besar (ini lebih mudah jika Anda melemparkan pid ke dalam output) sampai satu, jelas, telah mengklaim cukup bahwa yang lain gagal. Pemenang kemudian bebas untuk mengambil semuanya hingga CommitLimitminus Committed_AS.


4 Perlu disebutkan, pada titik ini, jika Anda belum memahami pengalamatan virtual dan paging permintaan, bahwa yang membuat komitmen lebih mungkin di tempat pertama adalah bahwa apa yang dialokasikan kernel untuk proseslandland bukanlah memori fisik sama sekali - itu adalah ruang alamat virtual . Misalnya, jika suatu proses menyimpan 10 MB untuk sesuatu, itu ditata sebagai urutan alamat (virtual), tetapi alamat tersebut belum sesuai dengan memori fisik. Ketika alamat tersebut diakses, ini menghasilkan kesalahan halamandan kemudian kernel mencoba untuk memetakannya ke memori nyata sehingga dapat menyimpan nilai nyata. Proses biasanya menyimpan lebih banyak ruang virtual daripada yang sebenarnya mereka akses, yang memungkinkan kernel membuat penggunaan RAM yang paling efisien. Namun, memori fisik masih merupakan sumber daya yang terbatas dan ketika semuanya telah dipetakan ke ruang alamat virtual, beberapa ruang alamat virtual harus dihilangkan untuk membebaskan beberapa RAM.


5 Pertama peringatan : Jika Anda mencoba ini vm.overcommit_memory=0, pastikan Anda menyimpan pekerjaan Anda terlebih dahulu dan menutup semua aplikasi penting, karena sistem akan dibekukan selama ~ 90 detik dan beberapa proses akan mati!

Idenya adalah untuk menjalankan bom garpu yang keluar setelah 90 detik, dengan garpu mengalokasikan ruang dan beberapa dari mereka menulis sejumlah besar data ke RAM, sambil melaporkan ke stderr.

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include <errno.h>
#include <string.h>

/* 90 second "Verbose hungry fork bomb".
Verbose -> It jabbers.
Hungry -> It grabs address space, and it tries to eat memory.

BEWARE: ON A SYSTEM WITH 'vm.overcommit_memory=0', THIS WILL FREEZE EVERYTHING
FOR THE DURATION AND CAUSE THE OOM KILLER TO BE INVOKED.  CLOSE THINGS YOU CARE
ABOUT BEFORE RUNNING THIS. */

#define STEP 1 << 30 // 1 GB
#define DURATION 90

time_t now () {
    struct timeval t;
    if (gettimeofday(&t, NULL) == -1) {
        fprintf(stderr,"gettimeofday() fail: %s\n", strerror(errno));
        return 0;
    }
    return t.tv_sec;
}

int main (void) {
    int forks = 0;
    int i;
    unsigned char *p;
    pid_t pid, self;
    time_t check;
    const time_t start = now();
    if (!start) return 1;

    while (1) {
    // Get our pid and check the elapsed time.
        self = getpid();
        check = now();
        if (!check || check - start > DURATION) return 0;
        fprintf(stderr,"%d says %d forks\n", self, forks++);
    // Fork; the child should get its correct pid.
        pid = fork();
        if (!pid) self = getpid();
    // Allocate a big chunk of space.
        p = malloc(STEP);
        if (!p) {
            fprintf(stderr, "%d Allocation failed!\n", self);
            return 0;
        }
        fprintf(stderr,"%d Allocation succeeded.\n", self);
    // The child will attempt to use the allocated space.  Using only
    // the child allows the fork bomb to proceed properly.
        if (!pid) {
            for (i = 0; i < STEP; i++) p[i] = i % 256;
            fprintf(stderr,"%d WROTE 1 GB\n", self);
        }
    }
}                        

Kompilasi ini gcc forkbomb.c -o forkbomb. Pertama, coba dengan sysctl vm.overcommit_memory=2- Anda mungkin akan mendapatkan sesuatu seperti:

6520 says 0 forks
6520 Allocation succeeded.
6520 says 1 forks
6520 Allocation succeeded.
6520 says 2 forks
6521 Allocation succeeded.
6520 Allocation succeeded.
6520 says 3 forks
6520 Allocation failed!
6522 Allocation succeeded.

Di lingkungan ini, bom fork semacam ini tidak terlalu jauh. Perhatikan bahwa angka dalam "kata N garpu" bukan jumlah total proses, itu adalah jumlah proses dalam rantai / cabang yang mengarah ke yang itu.

Sekarang coba dengan vm.overcommit_memory=0. Jika Anda mengarahkan stderr ke file, Anda dapat melakukan beberapa analisis kasar sesudahnya, misalnya:

> cat tmp.txt | grep failed
4641 Allocation failed!
4646 Allocation failed!
4642 Allocation failed!
4647 Allocation failed!
4649 Allocation failed!
4644 Allocation failed!
4643 Allocation failed!
4648 Allocation failed!
4669 Allocation failed!
4696 Allocation failed!
4695 Allocation failed!
4716 Allocation failed!
4721 Allocation failed!

Hanya 15 proses gagal mengalokasikan 1 GB - menunjukkan bahwa heuristik untuk overcommit_memory = 0 adalah dipengaruhi oleh negara. Berapa banyak proses yang ada di sana? Melihat akhir tmp.txt, mungkin> 100.000. Sekarang bagaimana sebenarnya bisa menggunakan 1 GB?

> cat tmp.txt | grep WROTE
4646 WROTE 1 GB
4648 WROTE 1 GB
4671 WROTE 1 GB
4687 WROTE 1 GB
4694 WROTE 1 GB
4696 WROTE 1 GB
4716 WROTE 1 GB
4721 WROTE 1 GB

Delapan - yang lagi-lagi masuk akal, karena pada saat itu saya punya ~ 3 GB RAM gratis dan 6 GB swap.

Lihatlah log sistem Anda setelah Anda melakukan ini. Anda harus melihat skor pelaporan pembunuh OOM (antara lain); mungkin ini berhubungan dengan oom_badness.

goldilocks
sumber
bertukar bukanlah solusi (atau bahkan terkait) dengan ingatan atas komitmen. Alokasi memori (misalnya: malloc) adalah tentang meminta memori virtual untuk dicadangkan, bukan fisik.
jlliagre
1
@ jillagre: "bertukar bukan solusi (atau bahkan terkait) untuk memori lebih dari komitmen" -> Ya, sebenarnya itu. Halaman-halaman yang jarang digunakan diganti dari RAM, sehingga lebih banyak RAM yang tersedia untuk mengatasi kesalahan halaman yang disebabkan oleh paging / alokasi permintaan (yang merupakan mekanisme yang memungkinkan komitmen berlebihan). Halaman yang ditukar mungkin juga harus diminta paged kembali ke RAM di beberapa titik.
goldilocks
"Alokasi memori (misalnya: malloc) adalah tentang meminta memori virtual untuk dicadangkan, bukan yang fisik." -> Benar, tetapi kernel bisa (dan secara opsional, akan) mengatakan tidak ketika tidak ada pemetaan fisik yang tersisa. Tentu tidak akan karena proses kehabisan ruang alamat virtual (atau setidaknya tidak biasanya, karena itu mungkin juga, setidaknya pada sistem 32-bit).
goldilocks
Permintaan paging bukan apa yang membuat memori lebih dari komitmen mungkin. Linux tentu saja melebihi komit memori pada sistem tanpa area swap sama sekali. Anda mungkin membingungkan ingatan atas komitmen dan permintaan paging. Jika Linux mengatakan "tidak" untuk malloc dengan proses 64 bit, yaitu jika tidak dikonfigurasikan untuk selalu overcommit, itu bisa karena korupsi memori atau karena jumlah semua reservasi memori (apakah dipetakan atau tidak ke RAM atau disk) melebihi ambang batas tergantung pada konfigurasi. Ini tidak ada hubungannya dengan penggunaan RAM karena mungkin terjadi bahkan ketika masih ada RAM gratis.
jlliagre
"Permintaan paging bukanlah yang membuat ingatan atas komitmen menjadi mungkin." -> Mungkin akan lebih baik untuk mengatakan bahwa itu adalah pengalamatan virtual yang memungkinkan paging permintaan dan komitmen berlebihan. "Linux tentu saja melebihi komit memori pada sistem tanpa area swap sama sekali." -> Jelas, karena permintaan paging tidak memerlukan swap; paging permintaan dari swap hanyalah contoh khusus dari paging permintaan. Sekali lagi, swap adalah solusi untuk komitmen yang berlebihan, bukan dalam arti bahwa itu menyelesaikan masalah, tetapi dalam arti yang akan membantu mencegah potensi peristiwa OOM yang mungkin timbul dari komitmen yang berlebihan.
goldilocks
16

Ini tidak akan terjadi pada Anda jika Anda hanya memuat 1G data ke dalam memori. Bagaimana jika Anda memuat lebih banyak? Sebagai contoh, saya sering bekerja dengan file besar yang berisi jutaan probabilitas yang perlu dimuat ke R. Ini membutuhkan sekitar 16GB RAM.

Menjalankan proses di atas pada laptop saya akan menyebabkannya mulai bertukar gila-gilaan segera setelah 8GB RAM saya telah terisi. Itu, pada gilirannya, akan memperlambat semuanya karena membaca dari disk jauh lebih lambat daripada membaca dari RAM. Bagaimana jika saya memiliki laptop dengan 2GB RAM dan hanya 10GB ruang kosong? Setelah proses mengambil semua RAM, itu juga akan mengisi disk karena sedang menulis untuk swap dan saya tidak memiliki RAM lagi dan tidak ada lagi ruang untuk swap (orang cenderung membatasi swap ke partisi khusus daripada sebuah swapfile untuk alasan itu). Di situlah pembunuh OOM masuk dan mulai membunuh proses.

Jadi, sistem memang bisa kehabisan memori. Selain itu, sistem swapping yang berat dapat menjadi tidak dapat digunakan jauh sebelum ini terjadi hanya karena operasi I / O yang lambat karena swapping. Orang umumnya ingin menghindari bertukar sebanyak mungkin. Bahkan pada server high-end dengan SSD cepat ada penurunan kinerja yang jelas. Di laptop saya, yang memiliki drive 7200RPM klasik, setiap pertukaran signifikan pada dasarnya membuat sistem tidak dapat digunakan. Semakin banyak swap, semakin lambat. Jika saya tidak membunuh proses pelanggaran dengan cepat semuanya hang sampai pembunuh OOM masuk

terdon
sumber
5

Proses tidak terbunuh ketika tidak ada lagi RAM, mereka terbunuh ketika mereka telah ditipu dengan cara ini:

  • Kernel Linux biasanya memungkinkan proses untuk mengalokasikan (yaitu cadangan) sejumlah memori virtual yang lebih besar dari apa yang sebenarnya tersedia (bagian dari RAM + semua area swap)
  • selama proses hanya mengakses sebagian dari halaman yang telah mereka pesan, semuanya berjalan dengan baik.
  • jika setelah beberapa waktu, suatu proses mencoba mengakses halaman yang dimilikinya tetapi tidak ada lagi halaman yang bebas, terjadi situasi kehabisan memori
  • Pembunuh OOM memilih salah satu proses, tidak harus yang meminta halaman baru, dan hanya membunuhnya untuk memulihkan memori virtual.

Ini mungkin terjadi bahkan ketika sistem tidak bertukar aktif, misalnya jika area swap diisi dengan halaman memori daemon yang tertidur.

Ini tidak pernah terjadi pada OS yang tidak kehabisan memori. Dengan mereka tidak ada proses acak yang terbunuh tetapi proses pertama yang meminta memori virtual saat itu habis memiliki malloc (atau yang serupa) kembali dalam kesalahan. Oleh karena itu diberikan kesempatan untuk menangani situasi dengan tepat. Namun, pada OS-OS ini, bisa juga terjadi sistem kehabisan memori virtual sementara masih ada RAM bebas, yang cukup membingungkan dan umumnya disalahpahami.

Jlliagre
sumber
3

Ketika RAM yang tersedia habis, kernel mulai menukar bit pemrosesan ke disk. Sebenarnya, kernel mulai bertukar ketika RAM hampir habis: kernel mulai bertukar secara proaktif saat momen idle, sehingga lebih responsif jika aplikasi tiba-tiba membutuhkan lebih banyak memori.

Perhatikan bahwa RAM tidak hanya digunakan untuk menyimpan memori proses. Pada sistem sehat yang khas, hanya sekitar setengah RAM yang digunakan oleh proses, dan setengah lainnya digunakan untuk cache disk dan buffer. Ini memberikan keseimbangan yang baik antara proses yang berjalan dan input / output file.

Ruang swap tidak terbatas. Pada titik tertentu, jika proses terus mengalokasikan semakin banyak memori, data spillover dari RAM akan mengisi swap. Ketika itu terjadi, proses yang mencoba untuk meminta lebih banyak memori melihat permintaan mereka ditolak.

Secara default, Linux overcommits memory. Ini berarti bahwa kadang-kadang akan memungkinkan proses untuk berjalan dengan memori yang telah dicadangkan, tetapi tidak digunakan. Alasan utama untuk memiliki komitmen berlebihan adalah cara forking bekerja. Ketika suatu proses meluncurkan subproses, proses anak secara konseptual beroperasi dalam replika memori orangtua - kedua proses awalnya memiliki memori dengan konten yang sama, tetapi konten tersebut akan berbeda ketika proses membuat perubahan masing-masing di ruang mereka sendiri. Untuk mengimplementasikan ini sepenuhnya, kernel harus menyalin semua memori induknya. Ini akan membuat forking lambat, sehingga kernel mempraktikkan copy-on-write: pada awalnya, anak berbagi semua ingatannya dengan orang tua; setiap kali salah satu proses menulis ke halaman yang dibagikan, kernel membuat salinan halaman itu untuk memecah berbagi.

Seringkali seorang anak akan meninggalkan banyak halaman tanpa tersentuh. Jika kernel mengalokasikan cukup memori untuk mereplikasi ruang memori induk pada setiap garpu, banyak memori akan terbuang sia-sia karena proses anak tidak akan pernah menggunakan. Karenanya overcommitting: kernel hanya mencadangkan sebagian dari memori itu, berdasarkan perkiraan berapa banyak halaman yang dibutuhkan anak.

Jika suatu proses mencoba mengalokasikan sebagian memori dan tidak ada cukup memori yang tersisa, proses tersebut menerima respons kesalahan dan menanganinya sesuai keinginan. Jika suatu proses secara tidak langsung meminta memori dengan menulis ke halaman bersama yang harus dibagikan, itu adalah cerita yang berbeda. Tidak ada cara untuk melaporkan situasi ini ke aplikasi: ia percaya bahwa ia memiliki data yang dapat ditulis di sana, dan bahkan bisa membacanya - hanya saja menulis melibatkan beberapa operasi yang sedikit lebih rumit di bawah tenda. Jika kernel tidak dapat memberikan halaman memori baru, yang bisa dilakukan hanyalah mematikan proses permintaan, atau membunuh beberapa proses lain untuk mengisi memori.

Anda mungkin berpikir pada titik ini bahwa membunuh proses permintaan adalah solusi yang jelas. Namun dalam praktiknya, ini tidak begitu baik. Prosesnya mungkin yang penting yang terjadi hanya perlu mengakses salah satu halamannya sekarang, sementara mungkin ada proses lain yang kurang penting berjalan. Jadi kernel menyertakan heuristik yang kompleks untuk memilih proses mana yang akan dibunuh - pembunuh OOM yang terkenal .

Gilles 'SANGAT berhenti menjadi jahat'
sumber
2

Hanya untuk menambahkan sudut pandang lain dari jawaban lain, banyak VPS meng-host beberapa mesin virtual pada server tertentu. Setiap VM tunggal akan memiliki jumlah RAM yang ditentukan untuk penggunaannya sendiri. Banyak penyedia menawarkan "burst RAM", di mana mereka dapat menggunakan RAM melebihi jumlah yang ditentukan. Ini dimaksudkan hanya untuk penggunaan jangka pendek, dan mereka yang melampaui jumlah waktu yang diperpanjang ini dapat dihukum oleh tuan rumah yang mematikan proses untuk menurunkan jumlah RAM yang digunakan sehingga orang lain tidak menderita mesin host kelebihan beban.

agweber
sumber
-1

Beberapa waktu linux membutuhkan ruang virtual eksternal. Itu adalah partisi swap. Ketika Ram diisi, linux mengambil area swap ini untuk menjalankan proses dengan prioritas rendah.

Bizzon
sumber
1
Tidak ada proses yang dijalankan dari swap. Memori virtual dibagi menjadi unit-unit berbeda berukuran sama yang disebut halaman. Ketika memori fisik dibebaskan, halaman dengan prioritas rendah diusir dari RAM. Sementara halaman dalam cache file memiliki dukungan sistem file, halaman anonim harus disimpan dalam swap. Prioritas halaman tidak terkait langsung dengan prioritas proses yang dimilikinya, tetapi seberapa sering halaman tersebut digunakan. Jika proses yang berjalan mencoba untuk mengakses halaman tidak dalam memori fisik, kesalahan halaman dihasilkan dan proses mendahului mendukung proses lain sedangkan halaman yang diperlukan (s) yang diambil dari disk.
Thomas Nyman