Почему Linux по умолчанию выделяет больше памяти?

В awk :

{
    for (i = 1; i <= NF; ++i) {
        printf("%d ", s += $i);
    }
    printf("\n");
}

Цикл перебирает все поля ввода и печатает текущую сумму ( s ) чисел. Переменная s не требует инициализации, так как ее значение будет принято равным нулю на первой итерации. Результатом присвоения s является значение s , которое затем печатается с завершающим символом пробела.

В примере ввода:

$ echo "1 5 6 8 9 11" | awk -f script.awk
1 6 12 20 29 40
1
29.05.2019, 15:54
2 ответа

Я думаю, причина в том, что не у всех людей есть достаточно ресурсов для покупки памяти, поэтому в таких случаях все приложения должны работать правильно, это помогает запускать приложения с низкими ресурсами.

-3
27.01.2020, 23:30

Большая часть потребности в избыточном выделении памяти в системах Linux (и Unix в целом )связана с необходимостью реализации системного вызова fork(), который дублирует адресное пространство вызывающего процесса.

Чаще всего за этим системным вызовом следует exec(), комбинация которых приводит к порождению отдельной программы в качестве потомка текущего процесса, и в этом случае большая часть дублированного адресного пространства в конечном итоге не будет использоваться.

Чтобы сделать это эффективным, Linux использует копирование -на -запись, чтобы избежать дублирования памяти приложения, вызывающего fork(), и в этом случае можно избежать копирования всех страниц, просто отбрасывая их вскоре после вызова exec().

Но в то время, когда вызывается fork(), невозможно сказать, придет ли exec(). Вполне возможно, что это используется для порождения рабочих дочерних элементов, и что желательно повторное использование адресного пространства родителя. (Этот метод был весьма популярен среди демонов, использующих предварительные -разветвленные рабочие процессы для обработки соединений. )В этом случае большая часть или, по крайней мере, некоторые из требований к памяти будут существовать для разветвленного дочернего элемента (возможно, не 100% памяти родителя, но можно предположить большую ее часть.)

Но всегда резервировать память для этого случая проблематично для случая fork()+ exec(), особенно если родительский процесс является долго -работающим процессом, который резервирует несколько гигабайт памяти и создает множество дочерних процессов. Если бы не overcommit, вам пришлось бы зарезервировать сумму, равную количеству гигабайтов, используемых родителем, и это для каждого разветвленного потомка.Но ничего (или почти ничего )из этого не было бы реально использовано, поскольку exec()сразу бы сняло эту оговорку. Конечным результатом является то, что такая рабочая нагрузка потребует либо огромного объема пространства подкачки (, чтобы справиться с резервированием, большая его часть будет неиспользована, но должна быть там на случай наихудшего случая )или что-то вроде overcommit.

Хотя fork()является отличной иллюстрацией этого примера, другие API в Linux/Unix также приводят к необходимости чрезмерного выделения. Например, когда malloc()вызывается (или, точнее, реализующие его системные вызовы ), никакая память фактически не выделяется до тех пор, пока процесс не «затронет» ее, поэтому вполне допустимо выделять очень большой блок гигабайт. и используйте это редко, чтобы фактически использовалось всего несколько мегабайт. Тот факт, что эти API работают таким образом, означает, что программы используют эти свойства, а это означает, что они, скорее всего, сломаются при отсутствии избыточной фиксации (, если только у вас действительно нет много памяти или свопа, которые можно тратить впустую, поддерживая эти резервирования.)

Интересное обсуждение проблемы с fork()можно найти в этой публикации LWN о статье Microsoft Research . Сама статья, конечно, интересная. Но вы же видите, как комментарии сразу переходят в оверкоммит и проблемы с ним.

Статья называется Развилка ()дороги .

4
27.01.2020, 23:30

Теги

Похожие вопросы