Ядро обнуляет память? - PullRequest
10 голосов
/ 15 мая 2011

Я использую сжатие Debian и заметил, что память всегда обнуляется.Это новое в дистрибутивах Linux?Некоторое время назад я полагал, что мог бы использовать put () и вывод мусора.

Я запускаю эту тестовую программу много раз, но закомментированные результаты всегда одинаковы.(У меня есть randomize_va_space = 2 в sysctl.conf, поэтому я знаю, что память в разных местах используется при каждом запуске.)


char *a = malloc(50000000);
a[49999999] = '\0';
puts(a); // it outputs nothing since all are zeroes
printf("%p\n", a);
if(a[5000] == '\0') // this condition is always true
{
    puts("It is a nul char.");
}

Возможно ли сделать систему не нулевой памятью?Какие опции могла бы активировать эта установка Debian squeeze, которая всегда обнуляет память?

Ответы [ 6 ]

18 голосов
/ 15 мая 2011

В любой современной операционной системе вновь полученная память будет содержать ненулевые значения, если память, ранее освобожденная вашей программой, была повторно использована malloc. Когда новая память получается из операционной системы (ядра), она изначально чисто виртуальная . У него нет физического существования; вместо этого он отображается как сопоставление копирования при записи одной страницы совместно используемой памяти, которая заполнена 0 байтами. При первой попытке записи в нее ядро ​​перехватит запись, выделит новую страницу физической памяти, скопирует содержимое исходной страницы (в данном случае все это 0 байтов) на новую страницу, а затем возобновит работу. ваша программа. Если ядро ​​знает, что вновь выделенная физическая память уже заполнена нулями, оно может даже оптимизировать шаг копирования.

Эта процедура является необходимой и эффективной. Это необходимо, потому что передача памяти, которая может содержать личные данные из ядра или процессов другого пользователя, будет критическим нарушением безопасности. Это эффективно, потому что обнуление не выполняется во время распределения; «заполненные нулями» страницы являются просто ссылкой на общую нулевую страницу.

7 голосов
/ 15 мая 2011

Из того, что я прочитал в Linux Kernel Development, ядро ​​делает нулевые страницы, потому что оно может содержать данные ядра, которые пользовательская программа может интерпретировать, и каким-то образом получить доступ к системе.

malloc запрашивает у ядра дополнительные страницы, поэтому ядро ​​отвечает за ту память, которую вы получаете.

3 голосов
/ 15 мая 2011

В первый раз, когда вы размещаете в памяти чанк-память, вполне вероятно, что она будет равна нулю, поскольку память, выделенная системным вызовом (sbrk, mmap), обнуляется ядром. Но если вы освободите и malloc снова, память будет переработана и может не содержать ноль.

1 голос
/ 16 мая 2011

Как уже показано, ключевое различие составляет распределение в первый раз против распределение .Если вы попробуете:

char *a, tst;
do {
    a = malloc(50000000);
    a[49999999] = '\0';
    printf("%50s\n%p", a, a); // it outputs nothing 1st, but bbbb.... 2nd
    tst = a[5000]
    memset(a, 'b', 50000000);
    free(a);
} while (tst == '\0');

, вы получите две строки (скорее всего, по крайней мере, если указатели совпадают).

Ключ в том, что блок памяти, возвращаемый malloc() имеет неопределенное содержимое .Это может быть или не быть нулем, и зависит от того, как программа выделяла память в прошлом (или какие средства отладки памяти используются).

Если вы хотите гарантировать содержимое, вам нужно calloc() или явная инициализация после выделения.

С другой стороны, гарантия целостности системы / разделения данных означает, что любое начальное адресное пространство, запрошенное системой, - либо через sbrk() или mmap(MAP_ANON) - должны быть инициализированы нулями, так как любое другое их содержимое может представлять собой брешь в системе безопасности.

1 голос
/ 15 мая 2011

Вы обнаружите, что в большинстве операционных систем, где есть изоляция между процессами, нулевая память. Причина заключается в том, что процессу нельзя позволять просматривать память, освобожденную другим процессом, поэтому страница памяти должна быть стерта между временем, когда она была освобождена каким-либо процессом, и временем, когда оно было освобождено другим процессом. На практике стирание означает обнуление, а память обычно обнуляется во время, выделенное процессом.

Когда вы вызываете malloc в своей игрушечной программе, память еще ни для чего не использовалась. Так что он все еще свежий из ядра, полный нулей. Если вы попробуете в реальной программе, которая уже выделена и освобождена, много блоков кучи, вы обнаружите, что память, которая уже использовалась вашим процессом , по-прежнему содержит любой мусор, который вы (или система управления памятью) можете поставили туда.

1 голос
/ 15 мая 2011

Ваш код не проверяет, обнулена ли вся память - он проверяет, равны ли два конкретных байта нулю - a [0] и a [5000].Кроме того, malloc () не имеет ничего общего с ядром - это функция библиотеки C, а не системный вызов.Крайне маловероятно, что его реализаторы обнуляют память - то, что вы видите, является просто случайной особенностью вашей конкретной конфигурации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...