Linux “RAM yetersiz kalabilir” mi?


20

Görünüşe göre çok fazla RAM kullandıkları için barındırılan bir VPS'den beklenmedik bir şekilde öldürme işlemleri hakkında şikayet eden insanların web çevresinde birkaç gönderi gördüm.

Bu nasıl mümkün olabilir? Ben tüm modern işletim sistemi sadece fiziksel RAM üzerinden ne olursa olsun disk takas kullanarak "sonsuz RAM" sağlamak düşündüm. Bu doğru mu?

Bir işlem "düşük RAM nedeniyle öldürülürse" ne olabilir?


12
Hiçbir işletim sisteminde sonsuz RAM yoktur. Makinelerdeki fiziksel RAM yongalarına ek olarak, işletim sistemleri - genellikle, isteğe bağlı olarak, diskte bulunan 'takas dosyasını' kullanabilir. Bir bilgisayarın RAM çubuklarında olduğundan daha fazla belleğe ihtiyacı olduğunda, bazı şeyleri takas dosyasına değiştirir. Ancak takas dosyası kapasitesine ulaştığında - maksimum boyut (tipik) ayarladığınız veya disk dolduğu için - sanal belleğiniz biter.
John Dibling

@JohnDibling; Bu yüzden dosya sistemi için disk alanı kazanmak dışında takas boyutunu sınırlamak isteyebilirsiniz herhangi bir nedeni var mı? Başka bir deyişle, 20 GB'lık bir disk ve yalnızca 1 GB'lık dosyam varsa, takas boyutumu 19 GB'a ayarlamam için bir neden var mı?
themirror

1
Bir şeyleri basitleştirmek için, takas boyutunu sınırlamanın iki sebebinin 1) disk tüketimini azaltmak ve 2) performansı artırmak olduğunu söyleyebilirim. İkincisi Windows altında / * NIX'ten daha doğru olabilir, ancak daha sonra , diskinizde takas alanı kullanıyorsanız , performansınız düşer. Disk erişimi, sisteme bağlı olarak RAM'den daha yavaş veya RAM'den çok daha yavaştır.
John Dibling

9
Takas RAM değildir . tr.wikipedia.org/wiki/Random-access_memory Sisteminizdeki RAM miktarı, sistem döneminizdeki RAM miktarıdır. Belirsiz veya dinamik bir hacim değildir. Kesinlikle düzeltildi. "Bellek" daha belirsiz bir kavramdır, ancak RAM ve diğer depolama biçimleri arasındaki fark, terdon'un (+1) işaret ettiği gibi, oldukça önemlidir. Disk değişimi birçok büyüklükte RAM'in yerine geçemez . Değişime aşırı derecede bağımlı olan bir sistem en iyi ihtimalle geçici ve genel olarak çöptür.
goldilocks

1
Disk alanı şimdi sonsuz mu?
Kaz

Yanıtlar:


41

Bir işlem "düşük RAM nedeniyle öldürülürse" ne olabilir?

Bazen linux'un varsayılan olarak uygulama kodundan daha fazla bellek isteğini hiçbir zaman reddetmediği söylenir - ör malloc(). 1 Bu aslında doğru değil; varsayılan, bir sezgisel tarama kullanır.

Açıkça adres alanı fazlalıkları reddedilir. Tipik bir sistem için kullanılır. Takas kullanımını azaltmak için fazla mesai yapılmasına izin verirken ciddi bir şekilde ayırmanın başarısız olmasını sağlar.

Kimden [linux_src]/Documentation/vm/overcommit-accounting(tüm alıntılar 3.11 ağacından alınmıştır). "Ciddi derecede vahşi bir tahsis" olarak kabul edilen şey tam olarak açıklığa kavuşturulamamıştır, bu yüzden ayrıntıları belirlemek için kaynaktan geçmemiz gerekir. Ayrıca, sezgisel bir bakış açısı elde etmek için dipnot 2'deki (aşağıda) deneysel yöntemi kullanabiliriz - buna dayanarak, ilk deneysel gözlemim, ideal koşullar altında (== sistem boştaysa), Herhangi bir takasınız yoksa, RAM'inizin yaklaşık yarısını ayırmanıza izin verilir ve takasınız varsa, RAM'inizin yaklaşık yarısını artı tüm takaslarınızı alırsınız. Yani daha fazla veya daha az işlem başına (ancak bu sınır not olduğunu , dinamik ve çünkü devletin değişikliğine tabi dipnot 5'de bazı gözlemler bakınız).

RAM artı takasınızın yarısı, "CommandLimit" alanı için açıkça varsayılan değerdir /proc/meminfo. İşte anlamı - ve sadece tartışılan sınırdan (hiçbirinden) hiçbir ilgisi olmadığını unutmayın [src]/Documentation/filesystems/proc.txt:

Komite Sınırı: Fazla taahhüt oranına ('vm.overcommit_ratio') dayanarak, bu sistemde tahsis edilebilecek toplam bellek miktarıdır . Bu sınıra yalnızca katı fazla taahhüt muhasebesi etkinse ('vm.overcommit_memory' deki mod 2) uyulur. CommandLimit aşağıdaki formülle hesaplanır: CommandLimit = ('vm.overcommit_ratio' * Fiziksel RAM) + Takas Örneğin, 1G fiziksel RAM ve 7G takas içeren 30'lu 'vm.overcommit_ratio' ile bir sistemde 7.3G'lık bir Taahhüt Sınırı.

Daha önce alıntılanan aşırı taahhüt muhasebesi dokümanı varsayılanın vm.overcommit_ratio50 olduğunu belirtir . Böylece, eğer sysctl vm.overcommit_memory=2vm.covercommit_ratio'yu (ile sysctl) ayarlayabilir ve sonuçlarını görebilirsiniz. 3 Varsayılan mod, CommitLimitzorlanmadığında ve yalnızca "adres alanının aşikar aşırılıkları reddedilir", modudur vm.overcommit_memory=0.

Varsayılan strateji, "ciddi vahşi tahsisi" önleyen sezgisel işlem başına bir sınıra sahip olsa da, sistemi ciddi bir şekilde vahşi hale getirmek için tahsis açısından akıllı bir şekilde serbest bırakır. 4 Bu, bir noktada belleğinin bitebileceği ve OOM katili aracılığıyla bazı işlemlere iflas beyan etmesi gerektiği anlamına gelir .

OOM katili ne öldürüyor? Mutlaka suçlu olmadığı zaman bellek isteyen süreç olması gerekmez, çünkü bu gerçekten suçlu süreç değildir ve daha da önemlisi, sistemi içinde bulunduğu sorundan en hızlı şekilde çıkaracak olan süreç değildir.

Buradan , muhtemelen 2.6.x kaynağından bahsedilir :

/*
 * 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)
 */

Bu iyi bir mantık gibi görünüyor. Ancak, adli tıp olmadan, # 5 (# 1 gereksiz) zor bir satış uygulaması akıllıca gibi görünüyor ve # 3 gereksiz # 2. Bu nedenle, # 2/3 ve # 4'e bölünmüş olarak düşünmek mantıklı olabilir.

Yakın zamanda bir kaynak (3.11) geçirdim ve bu yorumun geçici olarak değiştiğini fark ettim:

/**
 * 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.
 */

Bu biraz daha açık bir şekilde # 2 hakkında: "Amaç, daha sonraki oom arızalarından kaçınmak için en fazla belleği tüketen görevi [öldürmektir” ve ima # 4 ( "minimum işlem miktarını ( bir ) öldürmek istiyoruz ) ) .

OOM katilini çalışırken görmek için bkz. Dipnot 5.


1 Neyse ki Gilles beni kurtaran bir yanılgı, bkz. Yorumlar.


2 Daha fazla bilgi için bir isteğin ne zaman başarısız olacağını belirlemek için giderek daha büyük bellek yığınları isteyen basit bir C biti:

#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;
}            

C'yi bilmiyorsanız, bunu derleyip gcc virtlimitcheck.c -o virtlimitcheckçalıştırabilirsiniz ./virtlimitcheck. Süreç istediği alanın hiçbirini kullanmadığından tamamen zararsızdır, yani hiçbir zaman gerçekten RAM kullanmaz.

4 GB sistem ve 6 GB takas içeren 3.11 x86_64 sisteminde ~ 7400000 kB'de başarısız oldum; sayı dalgalanıyor, belki devlet bir faktör. Bu tesadüfen yakın olmaktır CommitLimitin /proc/meminfo, ancak bu aracılığıyla değiştirerek vm.overcommit_ratioherhangi bir fark yapmaz. 64 MB takas içeren bir 3.6.11 32-bit ARM 448 MB sisteminde, ~ 230 MB'da başarısızım. Bu ilginçtir, çünkü ilk durumda miktar RAM miktarının neredeyse iki katıdır, ikincisinde ise takas miktarını güçlü bir şekilde ima eden bir faktördür. Bu, başarısızlık eşiği ~ 1.95 GB'a düştüğünde, küçük ARM kutusuna çok benzer bir oran olan ilk sistemde takas kapatılarak doğrulandı.

Ama bu gerçekten süreç başına mı? Öyle görünüyor. Aşağıdaki kısa program, kullanıcı tanımlı bir bellek yığını ister ve başarılı olursa, geri dönmenizi bekler - bu şekilde birden fazla eşzamanlı örneği deneyebilirsiniz:

#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;
}

Bununla birlikte, kullanımdan bağımsız olarak RAM ve takas miktarıyla ilgili olmadığına dikkat edin - sistem durumunun etkileri hakkındaki gözlemler için 5. dipnota bakın.


3 , vm.overcommit_memory = 2 olduğunda sistemCommitLimit için izin verilen adres alanı miktarını ifade eder. 2 .Committed_AS

Bunu gösteren potansiyel olarak ilginç bir deney #include <unistd.h>, virtlimitcheck.c'nin (bkz. Dipnot 2) üstüne ve döngüden fork()hemen önce eklenmelidir while(). Bazı yorucu senkronizasyon olmadan burada açıklandığı gibi çalışacağı garanti edilmez, ancak YMMV'nin iyi bir şansı vardır:

> 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.

Bu mantıklıdır - tmp.txt'yi ayrıntılı olarak incelemek, süreçlerin daha büyük ve daha büyük ayırmalarını değiştirdiğini görebilirsiniz (pid'i çıktıya atarsanız daha kolaydır), açıkça, diğerinin başarısız olduğunu iddia edene kadar. Kazanan daha sonra her şeyi CommitLimiteksi olarak tutabiliyor Committed_AS.


4 Bu noktada, sanal adresleme ve talep çağrılamayı zaten anlamadıysanız, ilk etapta taahhüdü mümkün kılan şeyin, çekirdeğin kullanıcı alanı süreçlerine ayırdığı şeyin fiziksel bellek olmadığıdır. sanal adres alanı . Örneğin, bir işlem bir şey için 10 MB ayırırsa, bu (sanal) adresler dizisi olarak düzenlenir, ancak bu adresler henüz fiziksel belleğe karşılık gelmez. Böyle bir adrese erişildiğinde, bu bir sayfa hatasına neden olurve sonra çekirdek gerçek bir değer depolayabilmesi için gerçek belleğe eşlemeye çalışır. İşlemler genellikle gerçekte eriştiklerinden çok daha fazla sanal alan ayırır, bu da çekirdeğin RAM'i en verimli şekilde kullanmasını sağlar. Bununla birlikte, fiziksel bellek hala sınırlı bir kaynaktır ve tümü sanal adres alanına eşlendiğinde, bazı RAM'leri boşaltmak için bazı sanal adres alanlarının ortadan kaldırılması gerekir.


5 Önce bir uyarı : Bunu denerseniz vm.overcommit_memory=0, önce çalışmanızı kaydettiğinizden ve kritik uygulamaları kapattığınızdan emin olun, çünkü sistem ~ 90 saniye boyunca donar ve bazı işlemler ölür!

Fikir, çatalların yer ayırdığı ve bazıları RAM'e büyük miktarlarda veri yazdığı için 90 saniye sonra zaman aşımına uğrayan bir çatal bombası çalıştırmaktır .

#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);
        }
    }
}                        

Bunu derleyin gcc forkbomb.c -o forkbomb. İlk olarak, deneyin sysctl vm.overcommit_memory=2- muhtemelen şöyle bir şey elde edersiniz:

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.

Bu ortamda, bu tür çatal bombası çok uzaklara gitmiyor. "N çatalını söylüyor" daki sayının toplam işlem sayısı olmadığını, zincir / dalda buna giden işlemlerin sayısı olduğunu unutmayın.

Şimdi deneyin vm.overcommit_memory=0. Stderr'ı bir dosyaya yönlendirirseniz, daha sonra bazı ham analizler yapabilirsiniz, örneğin:

> 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!

= Overcommit_memory 0 buluşsal gösteren - sadece 15 süreçleri 1 GB ayıramadı olan devlet tarafından etkilenir. Kaç süreç vardı? Tmp.txt dosyasının sonuna bakıldığında, muhtemelen> 100.000. Şimdi gerçekte 1 GB'ı nasıl kullanabilir?

> 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

Sekiz - bu yine mantıklı, çünkü o zamanlar ~ 3 GB RAM boş ve 6 GB takas vardı.

Bunu yaptıktan sonra sistem günlüklerinize bir göz atın. OOM katil skorlarını görmelisiniz (diğer şeylerin yanı sıra); muhtemelen bu ile ilgilidir oom_badness.


yer değiştirmek takas konusunda belleğe bir çözüm (veya hatta ilgili) değildir. Bellek ayırma (örneğin: malloc), sanal belleğin fiziksel bellekten değil, rezerve edilmesini istemektir.
jlliagre

1
@jillagre: "takas bellek bağlılığı üzerine bellek için bir çözüm (hatta ilgili)" -> Evet, aslında öyle. Nadiren kullanılan sayfalar RAM'den çıkarılır ve talep sayfalaması / tahsisinin neden olduğu sayfa hatalarıyla başa çıkmak için daha fazla RAM kalır (bu, taahhüdü aşan bir mekanizmadır). Değiştirilen sayfaların da bir noktada talep edilen RAM'e geri çağrılması gerekebilir.
goldilocks

"Bellek ayırma (örn: malloc), sanal belleğin fiziksel bellek için değil, ayrılmış olmasını istemektir." -> Doğru, ancak çekirdek fiziksel eşleme kalmadığında hayır diyebilir (ve isteğe bağlı olarak) . Bunun nedeni, bir işlemin sanal adres alanı yetersiz kalması (ya da en azından genellikle değil, en azından 32 bit sistemlerde de mümkün olması) değildir.
goldilocks

Talep sayfalaması, bağlılığın üzerine hafızayı mümkün kılan şey değildir. Linux kesinlikle hiçbir takas alanı olmayan sistemlerde bellek fazla taahhüt. Taahhüt ve talep çağrılarıyla ilgili hafızayı karıştırıyor olabilirsiniz. Linux 64 bitlik bir işlemle malloc için "hayır" diyorsa, yani her zaman aşırı yüklenecek şekilde yapılandırılmamışsa, bunun nedeni bellek bozulması veya tüm bellek rezervasyonlarının toplamıdır (RAM veya diske eşlenmiş olsun olmasın). yapılandırmaya bağlı olarak bir eşik eşiğinin üzerindedir. Bunun RAM kullanımı ile ilgisi yoktur, çünkü hala boş RAM olsa bile olabilir.
jlliagre

"Talep sayfalaması, bağlılığın üzerine hafızayı mümkün kılan şey değildir." -> Belki de hem talep çağrılamayı hem de aşırı taahhüdü mümkün kılan sanal adresleme olduğunu söylemek daha iyi olur. "Linux kesinlikle hiçbir takas alanı olmayan sistemlerde bellek fazla taahhüt." -> Açıkçası, talep çağrılaması takas gerektirmediğinden; takastan talep çağrı sadece talep çağrı özel bir örneğidir. Bir kez daha, takas , sorunu çözdüğü anlamında değil, aşırı bağlılıktan kaynaklanabilecek OOM olaylarının önlenmesine yardımcı olacak anlamda aşırı bağlılığa bir çözümdür.
goldilocks

16

Belleğe yalnızca 1G veri yüklerseniz bu gerçekleşmez. Çok daha fazla yüklerseniz ne olur? Örneğin, genellikle R'ye yüklenmesi gereken milyonlarca olasılık içeren büyük dosyalarla çalışırım. Bu yaklaşık 16 GB RAM alır.

Yukarıdaki işlemi dizüstü bilgisayarımda çalıştırmak, 8GB RAM'im dolar doldurulmaz çılgın gibi değişmesine neden olur. Bu da her şeyi yavaşlatacaktır çünkü diskten okumak RAM'den okumaktan çok daha yavaştır. 2 GB RAM ve sadece 10 GB boş alana sahip bir dizüstü bilgisayarım varsa ne olur? İşlem tüm RAM'i aldıktan sonra, diski de dolduracaktır çünkü takas için yazıyor ve daha fazla RAM ve takas için daha fazla yer kalmıyorum (insanlar takasları tam olarak bu nedenle değiştirebilir). OOM katili devreye girer ve öldürme süreçlerine başlar.

Böylece, sistem gerçekten de belleği yetersiz kalabilir. Ayrıca, ağır takas sistemleri, takas nedeniyle yavaş G / Ç işlemleri nedeniyle, bu gerçekleşmeden çok önce kullanılamaz hale gelebilir. Kişi genellikle mümkün olduğunca değişmekten kaçınmak ister. Hızlı SSD'lere sahip üst düzey sunucularda bile performansta belirgin bir düşüş var. Klasik bir 7200 RPM sürücüsüne sahip dizüstü bilgisayarımda, herhangi bir önemli değişiklik sistemi kullanılamaz hale getiriyor. Ne kadar çok takas yaparsa o kadar yavaşlar. Saldırgan süreci çabucak öldürmezsem, OOM katili devreye girene kadar her şey asılı kalır.


5

Daha fazla RAM olmadığında süreçler öldürülmez, bu şekilde aldatıldıklarında öldürülürler:

  • Linux çekirdeği genellikle işlemlerin gerçekte mevcut olandan daha büyük bir miktar sanal bellek ayırmasına (yani ayırmasına) izin verir (RAM'in bir kısmı + tüm takas alanı)
  • işlemler yalnızca ayırdıkları sayfaların bir alt kümesine eriştiği sürece, her şey yolunda gider.
  • bir süre sonra, bir işlem sahip olduğu bir sayfaya erişmeye çalışırsa ancak başka sayfa boş değilse, yetersiz bellek durumu oluşur
  • OOM katili, işlemlerden birini seçer, yeni bir sayfa talep eden işlemi değil, yalnızca sanal belleği kurtarmak için onu öldürür.

Bu, sistem aktif olarak takas edilmese bile, örneğin takas alanı uyku cinleri bellek sayfalarıyla doluysa olabilir.

Bu asla belleği aşırı işlemeyen işletim sistemlerinde gerçekleşmez. Onlarla rastgele bir süreç öldürülmez, ancak tükendiğinde sanal bellek isteyen ilk işlemde hata (veya benzeri) malloc (veya benzeri) hataya döner. Bu nedenle, durumu doğru bir şekilde ele alma şansı verilir. Bununla birlikte, bu işletim sistemlerinde, sistemde hala boş bellek bulunurken, oldukça kafa karıştırıcı ve genellikle yanlış anlaşılan sistemde sanal bellek kalmıyor olabilir.


3

Kullanılabilir RAM tükendiğinde, çekirdek işleme bitlerini diske değiştirmeye başlar. Aslında, çekirdek RAM tükenmek üzereyken çekirdek değiştirmeye başlar: boş bir anı olduğunda proaktif olarak değişmeye başlar, böylece bir uygulama aniden daha fazla bellek gerektiriyorsa daha duyarlı olur.

RAM'in yalnızca işlemlerin belleğini depolamak için kullanılmadığını unutmayın. Tipik bir sağlıklı sistemde, RAM'in sadece yarısı süreçler tarafından kullanılırken, diğer yarısı disk önbelleği ve tamponlar için kullanılır. Bu, çalışan işlemler ve dosya giriş / çıkış arasında iyi bir denge sağlar.

Takas alanı sonsuz değildir. Bir noktada, süreçler daha fazla bellek ayırmaya devam ederse, RAM'deki yayılma verileri takası dolduracaktır. Bu durumda, daha fazla bellek istemeye çalışan işlemler isteklerinin reddedildiğini görür.

Varsayılan olarak, Linux belleği aşar . Bu, bazen bir işlemin ayırdığı ancak kullanmadığı bellekle çalışmasına izin vereceği anlamına gelir. Fazla taahhüde sahip olmanın temel nedeni, işlerin çatallanma yoludur . Bir süreç bir alt süreci başlattığında, alt süreç kavramsal olarak ebeveynin belleğinin bir kopyasında çalışır - iki işlem başlangıçta aynı içeriğe sahip belleğe sahiptir, ancak süreçler her biri kendi alanında değişiklik yaptıkça bu içerik farklılaşır. Bunu tam olarak uygulamak için, çekirdek ebeveynin tüm belleğini kopyalamak zorunda kalacaktır. Bu, çatallanmayı yavaşlatır, böylece çekirdek yazma üzerine kopyalamayı uygular: başlangıçta, çocuk tüm hafızasını ebeveyniyle paylaşır; her iki işlem de paylaşılan bir sayfaya yazdığında, çekirdek paylaşımı kırmak için o sayfanın bir kopyasını oluşturur.

Çoğu zaman bir çocuk birçok sayfaya dokunmaz. Çekirdek, her çataldaki ebeveynin bellek alanını çoğaltmak için yeterli bellek ayırdıysa, alt işlemlerin hiç kullanmayacağı rezervasyonlarda çok fazla bellek boşa harcanır. Bu nedenle aşırı taahhüt: çekirdek , çocuğun kaç sayfaya ihtiyacı olacağını tahmin ederek bu belleğin sadece bir kısmını ayırır .

Bir işlem bir miktar bellek ayırmaya çalışırsa ve yeterli bellek kalmazsa, işlem bir hata yanıtı alır ve uygun gördüğünde onunla ilgilenir. Bir süreç, paylaşılmaması gereken paylaşılan bir sayfaya yazarak dolaylı olarak bellek isterse, bu farklı bir hikaye. Bu durumu uygulamaya bildirmenin bir yolu yoktur: orada yazılabilir veriler olduğuna ve hatta okuyabileceğine inanır - sadece yazma başlığı altında biraz daha ayrıntılı bir işlem gerektirir. Çekirdek yeni bir bellek sayfası sağlayamıyorsa, yapabileceği tek şey istekte bulunan işlemi öldürmek veya belleği doldurmak için başka bir işlemi öldürmektir.

Bu noktada, talep sürecini öldürmenin bariz bir çözüm olduğunu düşünebilirsiniz. Ancak pratikte bu o kadar iyi değil. Süreç, şu anda yalnızca sayfalarından birine erişmesi gereken önemli bir süreç olabilirken, çalışan daha az önemli süreçler olabilir. Bu yüzden çekirdek, ünlü OOM katilini öldürecek süreçleri seçmek için karmaşık buluşsal yöntemler içerir .


2

Diğer cevaplardan başka bir bakış açısı eklemek için, birçok VPS'nin herhangi bir sunucuda birkaç sanal makine barındırması. Herhangi bir VM'nin kendi kullanımları için belirli bir RAM miktarı olacaktır. Birçok sağlayıcı, RAM'i belirledikleri miktarın ötesinde kullanabildikleri "seri RAM" sunar. Bu sadece kısa süreli kullanım içindir ve uzun bir süre bu sürenin ötesine geçen kişiler, kullanılan RAM miktarını azaltmak için ev sahibi öldürme işlemleri tarafından cezalandırılabilir, böylece diğerleri acı çekmez. ana makineye aşırı yükleniliyor.


-1

Bir süre linux harici sanal alan kaplar. Takas bölümü budur. Ram dolduğunda linux düşük öncelikli işlemi çalıştırmak için bu takas alanını alır.


1
Hiçbir işlem olup çalıştırmak takas. Sanal bellek, sayfa adı verilen eşit boyutta ayrı birimlere bölünür. Fiziksel bellek boşaltıldığında, düşük öncelikli sayfalar RAM'den çıkarılır. Dosya önbelleğindeki sayfalar dosya sistemi desteğine sahipken, anonim sayfalar takasta saklanmalıdır. Bir sayfanın önceliği, ait olduğu sürecin önceliği ile doğrudan ilgili değildir, ancak ne sıklıkta kullanıldığı ile ilgilidir. Çalışan bir işlem fiziksel bellekte olmayan bir sayfaya erişmeye çalışırsa, bir sayfa hatası oluşturulur ve gerekli sayfalar diskten getirilirken işlem başka bir işlem lehine önlenir .
Thomas Nyman
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.