2015-12-28 14 views
7

Ho scritto un semplice programma per limitare la dimensione dei dati a 65Kb e per verificare lo stesso sto allocando una memoria fittizia di oltre 65Kb e logicamente se sto facendo tutto correttamente (come sotto) chiamata malloc dovrebbe fallire, non è vero?Risorse di processo non limitate da 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; 
} 

Sorprendentemente, l'output è qualcosa di simile -

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 

faccio di sbagliato in qualche modo? Per favore lascia cadere i tuoi dati. Grazie!

+1

Il semplice ripristino dopo il messaggio "malloc failed" deve essere corretto per restituire 1 (o un valore diverso da zero). –

+1

Sto eseguendo ubntu linux 14.04 su amd64 con 8 giga di ram e compilazione usando gcc, con parametri: -Wall -Wextra -pedantic -std-c99. Ciò risulta nel compilatore che emette i seguenti tre avvisi. 1) riga 41: 9: avviso: 'return' senza valore, in funzione restituzione not-void 2) parametro inutilizzato argc 3) parametro inutilizzato argv. Quando si fa una domanda su un problema di runtime, inserire sempre il codice che compila in modo pulito. – user3629249

risposta

3

Dal setrlimit man page:

RLIMIT_DATA

La dimensione massima del segmento dati del processo (inizializzato dati, i dati non inizializzati e heap). Questo limite influisce sulle chiamate a brk (2) e sbrk (2), che non riescono con l'errore ENOMEM su incontrando il limite flessibile di questa risorsa.

In particolare, tale risorsa non si applica alla memoria ottenuta tramite mmap. Internamente malloc utilizza vari meccanismi per ottenere nuova memoria. In questo caso troverai che utilizzava mmap e non sbrk o brk. Puoi verificarlo scaricando le chiamate di sistema dal tuo programma con strace.

Per ottenere ciò che si desidera, utilizzare invece la risorsa RLIMIT_AS.

+0

Apparentemente una patch del kernel Linux ha lo scopo di risolverlo, ma a quanto pare non è ancora entrata nel kernel (almeno, non è in esecuzione l'OP, o quello che sto eseguendo). Ecco una descrizione insieme alla patch: [Patch RLIMIT_DATA] (http://lkml.iu.edu/hypermail/linux/kernel/0707.1/0675.html) –

+0

@kaylum Esattamente quello di cui avevo bisogno! e sì, sei corretto in questo caso la memoria è allocata da 'mmap'. Ho verificato questo tramite la chiamata di malloc_stats(). uscita dello stesso è stato qualcosa di simile - Arena 0: sistema byte = 0 in uso byte = 0 totale (incl mmap.): sistema di byte = 66.670.592 in uso byte = 66670592 regioni max mmap = 1 max mmap byte = 66670592 Ora sono curioso di sapere su mmap, eventuali input o collegamenti per lo stesso? :) – Coder

+0

@Coder Dipende da cosa vuoi sapere su 'mmap'. Ma certamente la [pagina man di mmap] (http://linux.die.net/man/2/mmap) è il punto di partenza se non l'hai già letto. – kaylum

1

dopo aver corretto i problemi con la compilazione del codice.

Questo è il codice:

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

e qui è l'output:

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 

che indica la modifica alle opere RLIMITE, la chiamata system ha avuto successo, il comando bash fallito, e il malloc ha avuto successo.

più esecuzioni dello stesso codice sempre uscita gli esatti valori stessi quindi nessun cambiamento permanente al valore rlimit

dopo l'esecuzione del codice precedente più volte, lasciando ogni finestra terminale aperto, quindi eseguire il comando bash in ancora un'altra finestra terminale ha portato alla seguente:

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 

poi eseguire il codice in un altro terminale poi eseguire il comando bash nello stesso terminale di uscita i valori esatti stessi uscita.

Pertanto, sospetto che il codice stia prendendo l'approccio sbagliato per limitare la quantità di memoria disponibile.

+1

Questo non risolve la domanda, motivo per cui l'impostazione di RLIMIT_DATA non riesce a limitare la dimensione del segmento di dati. Se funzionasse, malloc fallirebbe, che è quello che l'OP si aspettava. –

+0

fa notare che 1) il cambiamento è transitorio piuttosto che permanente 2) è stato adottato l'approccio sbagliato. 3) a causa di 'memoria virtuale' e' memoria di paging', la riduzione dell'attuale RAM disponibile in un programma renderà, al massimo, il programma più lento mentre la memoria più piccola disponibile genera più eventi di 'pagina fault' ma è altrimenti di scarso interesse. 4) 'malloc' non richiede che la memoria allocata venga effettivamente allocata in ram fino a quando non viene effettivamente utilizzata e anche quelle pagine solo durante l'accesso. – user3629249

+0

Il punto importante è che RLIMIT_DATA non ha l'effetto desiderato negli attuali kernel di Linux, e OP dovrebbe invece usare RLIMIT_AS. Vedi la risposta e la spiegazione di keylum. –