Как делать трубопроводы ограничить использование памяти?

На Raspberry Pi 2 Model B удаление строки local 192.168... строку из /etc/openvpn/server.conf устранило эту проблему. См. https://bbs.archlinux.org/viewtopic.php?id=183818 для получения дополнительной информации об этом.

37
21.06.2018, 13:48
3 ответа

Данные не обязательно хранить в оперативной памяти. Пайпы блокируют своих авторов, если читателей нет или они не успевают за ними; в Linux (и большинстве других реализаций, я полагаю, )есть некоторая буферизация, но она не требуется. Как упоминалось mtraceur и JdeBP (, см. ответ последнего ), ранние версии Unix буферизовали каналы на диск, и именно так они помогли ограничить использование памяти :. конвейер обработки может быть разбит на небольшие программы, каждая из которых будет обрабатывать некоторые данные в пределах дисковых буферов. Небольшие программы занимают меньше памяти, а использование конвейеров означало, что обработка может быть сериализована :: первая программа будет запускаться, заполнять свой выходной буфер, приостанавливаться, затем будет планироваться вторая программа, обрабатывать буфер и т. д. Современные системы на порядки больше, чем ранние системы Unix, и могут запускать множество каналов параллельно; но для огромных объемов данных вы все равно увидите аналогичный эффект (, и варианты этого метода используются для обработки «больших данных» ).

В вашем примере

sed 'simplesubstitution' file | sort | uniq > file2

sedсчитывает данные из fileпо мере необходимости, затем записывает их до тех пор, пока sortготов их прочитать; если sortне готов, запись блокируется. Данные действительно остаются в памяти в конечном итоге, но это характерно для sort, и sortготов решать любые проблемы (, он будет использовать временные файлы, если количество данных для сортировки слишком велико ).

Вы можете увидеть поведение блокировки, запустив

strace seq 1000000 -1 1 | (sleep 120; sort -n)

Это производит достаточное количество данных и направляет их процессу, который не готов что-либо читать в течение первых двух минут. Вы увидите, как выполняется ряд writeопераций,но очень быстро seqостановится и будет ждать две минуты, заблокированные ядром (системный вызов writeждет ).

50
27.01.2020, 19:36

But I don't understand how this could limit memory usage considering the fact that the data has to be stored in RAM to transmit between programs.

Это ваша фундаментальная ошибка. Ранние версии Unix не хранили данные канала в оперативной памяти. Они сохранили их на диске. Трубы имели i -узлов; на дисковом устройстве, которое было обозначено трубным устройством . Системный администратор запустил программу с именем /etc/config, чтобы указать (, среди прочего ), какой том на каком диске является конвейерным устройством, какой том является корневым устройством и какой устройство сброса .

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

Этот механизм был заменен другими в середине-конце 1980-х годов. SCO XENIX получила «Высокопроизводительную конвейерную систему», которая заменила i -узлов на -основных буферов. 4BSD превратил неименованные каналы в пары сокетов. AT&T повторно реализовала конвейеры, используя механизм STREAMS.

И, конечно же, программа sortвыполняла ограниченную внутреннюю сортировку фрагментов ввода по 32 КБ (или любой меньший объем памяти, который она могла выделить, если бы 32 КБ были недоступны ),запись отсортированных результатов в промежуточные stmX??файлы в /usr/tmp/, которые затем отсортированы извне, чтобы обеспечить окончательный вывод.

Дополнительная литература

  • Стив Д. Пейт (1996 ). «Интер -процесс связи». Внутреннее устройство UNIX :Практический подход . Аддисон -Уэсли. ISBN 9780201877212.
  • Морис Дж. Бах (1987 ). «Системные вызовы файловой системы». Дизайн операционной системы Unix . Прентис -Холл. ISBN 0132017571.
  • Стивен В. Эрхарт (1986 ). «config( 1М )». Руководство программиста Unix :3. Средства системного администрирования . Холт, Райнхарт и Уинстон. ISBN 0030093139. стр. 23–28.
  • Абхиджит Менон -Сен (2020 -03 -23 ).Как реализуются каналы Unix?. toroid.org.
36
27.01.2020, 19:36

Вы частично правы, но только случайно .

В вашем примере все данные действительно должны быть прочитаны «между» каналами, но они не обязательно должны находиться в памяти (, включая виртуальную память ). Обычные реализации sortмогут сортировать наборы данных, которые не помещаются в ОЗУ, путем частичной сортировки временных файлов и слияния. Однако фактом является то, что вы не можете вывести отсортированную последовательность, не прочитав каждый элемент. Это довольно очевидно. Так что да, sortможет начать вывод во второй канал только после того, как прочитает (и сделает что-то еще, возможно, частично отсортировав временные файлы )все, начиная с первого. Но не обязательно хранить все это в оперативной памяти.

Однако это не имеет ничего общего с тем, как работают трубы. Каналы могут быть названы (, традиционно они все назывались ), что означает не более и не менее того, что они имеют место в файловой системе, как и файлы. И это именно то, чем когда-то были каналы, файлы (с записями объединялись настолько, насколько позволяла доступность физической памяти, в качестве оптимизации ).

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

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

Философия множества простых программ была наиболее полезна когда-то, когда памяти было очень мало. Потому что, ну, вы могли бы выполнять работу маленькими шагами, один за другим. В настоящее время преимущества, кроме некоторой дополнительной гибкости, я осмелюсь сказать, уже не так велики.
Однако пайпы реализованы очень эффективно (они должны были быть! ), так что недостатка тоже нет, это устоявшаяся вещь, которая отлично работает и к которой люди привыкли, так что нет необходимости менять парадигму.

1
27.01.2020, 19:36

Теги

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