2015-12-28 6 views
7

Ich schrieb ein einfaches Programm, um seine Datengröße zu 65Kb zu beschränken und zu überprüfen, die ich bin ein Dummy-Speicher von mehr als 65Kb zuweisen und logisch, wenn ich alle richtigen (wie unten) malloc Anruf sollte scheitern, oder?Verarbeitet Ressourcen nicht begrenzt durch setrlimit

#include <sys/resource.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 

int main (int argc, char *argv[]) 
{ 
    struct rlimit limit; 


    /* Get max data size . */ 
    if (getrlimit(RLIMIT_DATA, &limit) != 0) { 
    printf("getrlimit() failed with errno=%d\n", errno); 
    return 1; 
    } 

    printf("The soft limit is %lu\n", limit.rlim_cur); 
    printf("The hard limit is %lu\n", limit.rlim_max); 

    limit.rlim_cur = 65 * 1024; 
    limit.rlim_max = 65 * 1024; 

    if (setrlimit(RLIMIT_DATA, &limit) != 0) { 
    printf("setrlimit() failed with errno=%d\n", errno); 
    return 1; 
    } 

    if (getrlimit(RLIMIT_DATA, &limit) != 0) { 
    printf("getrlimit() failed with errno=%d\n", errno); 
    return 1; 
    } 

    printf("The soft limit is %lu\n", limit.rlim_cur); 
    printf("The hard limit is %lu\n", limit.rlim_max); 
    system("bash -c 'ulimit -a'"); 
    int *new2 = NULL; 
    new2 = malloc(66666666); 
    if (new2 == NULL) 
    { 
     printf("malloc failed\n"); 
     return; 
    } 
    else 
    { 
     printf("success\n"); 
    } 

    return 0; 
} 

Überraschenderweise ist die ouput so etwas wie dieses -

The soft limit is 4294967295 
The hard limit is 4294967295 
The soft limit is 66560 
The hard limit is 66560 
core file size   (blocks, -c) 0 
data seg size   (kbytes, -d) 65 
scheduling priority    (-e) 0 
file size    (blocks, -f) unlimited 
pending signals     (-i) 14895 
max locked memory  (kbytes, -l) 64 
max memory size   (kbytes, -m) unlimited 
open files      (-n) 1024 
pipe size   (512 bytes, -p) 8 
POSIX message queues  (bytes, -q) 819200 
real-time priority    (-r) 0 
stack size    (kbytes, -s) 8192 
cpu time    (seconds, -t) unlimited 
max user processes    (-u) 14895 
virtual memory   (kbytes, -v) unlimited 
file locks      (-x) unlimited 
success 

Bin ich in irgendeiner Weise falsch? Bitte lassen Sie Ihre Eingaben fallen. Danke!

+1

Die leere Rückkehr nach der Meldung "malloc failed" sollte behoben werden, um 1 (oder einen Wert ungleich Null) zurückzugeben. –

+1

Ich benutze Ubntu Linux 14.04 Amd64 mit 8 Gigs RAM, und kompilieren mit gcc, mit Parametern: -Wall -Wextra -pedantisch -std-c99. Dies führt dazu, dass der Compiler die folgenden drei Warnungen ausgibt. 1) Zeile 41: 9: warning: 'return' ohne Wert, in Funktion return not-void 2) unbenutzter Parameter argc 3) unbenutzter Parameter argv. Wenn Sie eine Frage zu einem Laufzeitproblem stellen, geben Sie immer Code ein, der sauber kompiliert wird. – user3629249

Antwort

3

Vom setrlimit man page:

RLIMIT_DATA

Die maximale Größe des Datensegments des Prozesses ( Daten, nicht initialisierte Daten initialisiert und Heap). Diese Begrenzung wirkt sich auf Aufrufe auf brk (2) und sbrk (2) aus, die mit dem Fehler ENOMEM bei beim Auftreten der weichen Grenze dieser Ressource fehlschlagen.

Diese Ressource gilt nicht für den Speicher, der über mmap erhalten wird. Intern verwendet malloc verschiedene Mechanismen, um neuen Speicher zu erhalten. In diesem Fall finden Sie, dass es mmap und nicht sbrk oder brk verwendet. Sie können dies überprüfen, indem Sie die Systemaufrufe von Ihrem Programm mit strace dumpen.

Um zu erreichen, was Sie wollen, verwenden Sie stattdessen die Ressource RLIMIT_AS.

+0

Es gibt anscheinend einen Linux-Kernel-Patch, der darauf abzielen soll, aber anscheinend hat er es noch nicht in den Kernel geschafft (zumindest nicht das eine OP oder das, das ich gerade betreibe). Hier ist eine Beschreibung zusammen mit dem Patch: [RLIMIT_DATA Patch] (http://lkml.iu.edu/hypermail/linux/kernel/0707.1/0675.html) –

+0

@ Kaylum Genau das, was ich brauchte! und ja du bist richtig in diesem Fall Speicher wird von 'mmap' zugewiesen. Ich habe dies durch den Aufruf von malloc_stats() lib verifiziert. Ausgang desselben war so etwas - Arena 0: System Bytes = 0 in Gebrauch Bytes = 0 Gesamtpreis (inkl mmap.): System Bytes = 66670592 im Einsatz Bytes = 66670592 max Mmap Regionen = 1 max mmap bytes = 66670592 Jetzt bin ich neugierig auf mmap, irgendwelche Eingänge oder Links für die gleichen? :) – Coder

+0

@Coder Hängt davon ab, was Sie über 'mmap' wissen möchten. Aber sicherlich ist die [mmap man page] (http://linux.die.net/man/2/mmap) der richtige Ort, wenn Sie es noch nicht gelesen haben. – kaylum

1

nach der Korrektur der Probleme mit der Kompilierung des Codes.

Dies ist der Code:

#include <sys/resource.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 

int main (void) 
{ 
    struct rlimit limit; 


    /* Get max data size . */ 
    if (getrlimit(RLIMIT_DATA, &limit) != 0) { 
    printf("getrlimit() failed with errno=%d\n", errno); 
    exit(EXIT_FAILURE); 
    } 

    printf("The soft limit is %lu\n", limit.rlim_cur); 
    printf("The hard limit is %lu\n", limit.rlim_max); 

    limit.rlim_cur = 65 * 1024; 
    limit.rlim_max = 65 * 1024; 

    if (setrlimit(RLIMIT_DATA, &limit) != 0) 
    { 
    printf("setrlimit() failed with errno=%d\n", errno); 
    exit(EXIT_FAILURE); 
    } 

    if (getrlimit(RLIMIT_DATA, &limit) != 0) 
    { 
    printf("getrlimit() failed with errno=%d\n", errno); 
    exit(EXIT_FAILURE); 
    } 

    printf("The soft limit is %lu\n", limit.rlim_cur); 
    printf("The hard limit is %lu\n", limit.rlim_max); 
    system("bash -c 'ulimit -a'"); 

    int *new2 = NULL; 
    new2 = malloc(66666666); 

    if (new2 == NULL) 
    { 
     printf("malloc failed\n"); 
     exit(EXIT_FAILURE); 
    } 
    else 
    { 
     printf("success\n"); 
    } 

    return 0; 
} 

und hier ist die Ausgabe:

The soft limit is 18446744073709551615 
The hard limit is 18446744073709551615 
The soft limit is 66560 
The hard limit is 66560 
bash: xmalloc: .././variables.c:2307: cannot allocate 48 bytes (16384 bytes allocated) 
success 

, die die Änderung der rlimit Werke zeigt, die system Aufruf war erfolgreich, die bash Befehl fehlgeschlagen ist, und die malloc war erfolgreich.

Mehrere Durchläufe des gleichen Code immer ausgegeben exakt die gleichen Werte, so dass keine dauerhafte Änderung des rlimit Wert

nach dem obigen Code mehrmals ausgeführt wird, während jedes Terminal-Fenster offen zu lassen, dann in noch das bash Befehl ausführen ein weiteres Terminal-Fenster ergab folgendes:

core file size   (blocks, -c) 0 
data seg size   (kbytes, -d) unlimited 
scheduling priority    (-e) 0 
file size    (blocks, -f) unlimited 
pending signals     (-i) 54511 
max locked memory  (kbytes, -l) 64 
max memory size   (kbytes, -m) unlimited 
open files      (-n) 1024 
pipe size   (512 bytes, -p) 8 
POSIX message queues  (bytes, -q) 819200 
real-time priority    (-r) 0 
stack size    (kbytes, -s) 8192 
cpu time    (seconds, -t) unlimited 
max user processes    (-u) 54511 
virtual memory   (kbytes, -v) unlimited 
file locks      (-x) unlimited 

dann noch in einem anderen Terminal den Code läuft dann in der gleichen Klemme Ausgang exakt die gleichen Ausgangswerte der bash Befehl ausgeführt wird.

Daher vermute ich, dass der Code den falschen Ansatz zur Begrenzung der verfügbaren Speichermenge verwendet.

+1

Dies behandelt die Frage nicht, weshalb die Einstellung RLIMIT_DATA die Datensegmentgröße nicht begrenzen kann. Wenn es funktionierte, würde malloc scheitern, was OP erwartet hatte. –

+0

es weist darauf hin, dass 1) die Änderung eher vorübergehend als dauerhaft 2) ist, wird der falsche Ansatz genommen. 3) aufgrund von "virtuellem Speicher" und "Speicher-Paging" führt die Reduzierung des tatsächlich verfügbaren RAM zu einem Programm höchstens dazu, dass das Programm langsamer läuft, da der kleinere verfügbare Speicher mehr "Seitenfehler" -Ereignisse zur Folge hat ansonsten von wenig Interesse. 4) 'malloc' erfordert nicht den zugewiesenen Speicher, um tatsächlich in RAM zugewiesen zu werden, bis/wann es tatsächlich verwendet wird, und sogar diese Seiten nur während es tatsächlich zugegriffen wird – user3629249

+0

Der wichtige Punkt ist, dass RLIMIT_DATA nicht den gewünschten Effekt hat in aktuellen Linux-Kerneln und OP sollte stattdessen RLIMIT_AS verwenden. Siehe keylum's Antwort und Erklärung. –

Verwandte Themen