Скорость передачи данных (Baud) — это единица измерения скорости передачи в асинхронной связи. Из-за развития технологий модемной связи этот термин часто ошибочно используют для описания скорости передачи данных в современных устройствах.
-Традиционно, скорость передачи (Baud Rate) представляет количество битов, фактически передаваемых по среде, а не объем данных, которые действительно перемещаются от одного устройства DTE к другому. Подсчет Baud включает служебные биты — Start, Stop и Parity, которые генерируются передающим UART и удаляются принимающим UART. Это означает, что 7-битные слова данных на самом деле занимают 10 бит для полной передачи. Следовательно, модем, способный передавать 300 бит в секунду, обычно может передавать только 30 7-битных слов, если используется Parity и присутствуют один бит Start и один бит Stop.
+Традиционно, скорость передачи (Baud Rate) представляет количество битов, фактически передаваемых по среде, а не объём данных, которые действительно перемещаются от одного устройства DTE к другому. Подсчет Baud включает служебные биты — Start, Stop и Parity, которые генерируются передающим UART и удаляются принимающим UART. Это означает, что 7-битные слова данных на самом деле занимают 10 бит для полной передачи. Следовательно, модем, способный передавать 300 бит в секунду, обычно может передавать только 30 7-битных слов, если используется Parity и присутствуют один бит Start и один бит Stop.
Если используются 8-битные слова данных и биты чётности, скорость передачи данных снижается до 27,27 слов в секунду, так как теперь для передачи восьмибитных слов требуется 11 бит, а модем по-прежнему передаёт только 300 бит в секунду.
@@ -487,7 +487,7 @@
Когда компания National Semiconductor разработала NS16550, она получила несколько патентов на эту конструкцию и также ограничила лицензирование, что затруднило для других производителей выпуск чипов с аналогичными характеристиками. В результате патентов обратно спроектированные конструкции и эмуляции должны были избегать нарушения пунктов, охватываемых патентами. Впоследствии эти копии почти никогда не работают точно так же, как NS16550A или PC16550D, которые являются компонентами, наиболее востребованными производителями компьютеров и модемов, но иногда они не готовы платить цену, необходимую для получения оригинальных деталей.
-Некоторые различия в клонах микросхем 16550A несущественны, в то время как другие могут полностью препятствовать использованию устройства с определенной операционной системой или драйвером. Эти различия могут проявиться при использовании других драйверов или при возникновении определенных комбинаций событий, которые не были хорошо протестированы или учтены в драйвере Windows(R). Это происходит потому, что большинство производителей модемов и клонов 16550 используют драйверы Microsoft из Windows(R) for Workgroups 3.11 и утилиту Microsoft(R) MS-DOS(R) в качестве основных тестов на совместимость с NS16550A. Этот чрезмерно упрощенный критерий означает, что при использовании другой операционной системы могут возникнуть проблемы из-за тонких различий между клонами и оригинальными компонентами.
+Некоторые различия в клонах микросхем 16550A несущественны, в то время как другие могут полностью препятствовать использованию устройства с определённой операционной системой или драйвером. Эти различия могут проявиться при использовании других драйверов или при возникновении определённых комбинаций событий, которые не были хорошо протестированы или учтены в драйвере Windows(R). Это происходит потому, что большинство производителей модемов и клонов 16550 используют драйверы Microsoft из Windows(R) for Workgroups 3.11 и утилиту Microsoft(R) MS-DOS(R) в качестве основных тестов на совместимость с NS16550A. Этот чрезмерно упрощенный критерий означает, что при использовании другой операционной системы могут возникнуть проблемы из-за тонких различий между клонами и оригинальными компонентами.
National Semiconductor предоставила программу под названием COMTEST, которая выполняет тесты совместимости независимо от каких-либо драйверов ОС. Следует помнить, что цель такого типа программ — демонстрация недостатков в продуктах конкурентов, поэтому программа будет сообщать как о значительных, так и о крайне незначительных различиях в поведении тестируемого компонента.
UART 8250/16450/16550 занимает восемь последовательных адресов портов ввода-вывода. В IBM PC определены два расположения для этих восьми портов, которые вместе известны как [.filename]#COM1# и [.filename]#COM2#. Производители PC-клонов и дополнительных карт создали два дополнительных области, известных как [.filename]#COM3# и [.filename]#COM4#, но эти дополнительные COM-порты конфликтуют с другим оборудованием на некоторых системах. Наиболее распространённый конфликт возникает с видеоадаптерами, обеспечивающими эмуляцию IBM 8514.
@@ -686,7 +686,7 @@
|Регистр состояния линии (LSR — Line Status Register) +
Бит 7 -> Ошибка в FIFO приемника. На UART 8250/16450 этот бит равен нулю. Этот бит устанавливается в «1», когда любой из байтов в FIFO имеет одно или несколько из следующих условий ошибки: PE, FE или BI. +
Бит 6 -> Передатчик пуст (TEMT). Когда установлен в «1», в FIFO передатчика или сдвиговом регистре передатчика не осталось слов. Передатчик полностью бездействует. +
-Бит 5 -> Регистр хранения передатчика пуст (THRE). Когда установлен в «1», в FIFO (или регистре хранения) теперь есть место для передачи как минимум одного дополнительного слова. Передатчик может все еще передавать данные, когда этот бит установлен в «1». +
+Бит 5 -> Регистр хранения передатчика пуст (THRE). Когда установлен в «1», в FIFO (или регистре хранения) теперь есть место для передачи как минимум одного дополнительного слова. Передатчик может все ещё передавать данные, когда этот бит установлен в «1». +
Бит 4 -> Прерывание по Break (BI). Приемник обнаружил сигнал Break. +
Бит 3 -> Ошибка кадрирования (FE). Обнаружен стартовый бит, но стоповый бит не появился в ожидаемое время. Принятое слово, вероятно, искажено. +
Бит 2 -> Ошибка чётности (PE). Бит чётности для принятого слова был некорректен. +
В этой статье описывается использование твердотельных дисковых устройств для создания встраиваемых систем на основе FreeBSD.
-Встраиваемые системы имеют преимущество в повышенной надёжности по причине отсутствия в них движущихся частей (жестких дисков). Однако, следует принять во внимание, что системе, как правило, доступно очень малое дисковое пространство и ограниченный объем запоминающего устройства.
+Встраиваемые системы имеют преимущество в повышенной надёжности по причине отсутствия в них движущихся частей (жёстких дисков). Однако, следует принять во внимание, что системе, как правило, доступно очень малое дисковое пространство и ограниченный объём запоминающего устройства.
К отдельно рассматриваемым вопросам относятся типы и характеристики твердотельных носителей, подходящих для использования в качестве дисков во FreeBSD, параметры ядра, которые представляют интерес в таких условиях, механизмы [.filename]#rc.initdiskless#, автоматизирующие инициализацию таких систем и удовлетворяющие требованиям файловых систем, доступных только для чтения, а также построение файловых систем с нуля. Статья заканчивается описанием некоторых общих стратегий для случаев малых систем FreeBSD и работ в режиме только для чтения.
@@ -57,7 +57,7 @@
[[intro]]
== Твердотельные дисковые устройства
-Эта статья будет ограничиваться рассмотрением твердотельных дисковых устройств, которые делаются на основе флеш-памяти. Флеш-память является твердотельным (здесь нет движущихся частей) запоминающим устройством, которое является энергонезависимым (данные остаются в памяти даже после отключения всех источников питания). Флеш-память может быть нечувствительной к сильным физическим воздействиям и достаточно быстра (решения на основе флеш-памяти, описываемые в этой статье, гораздо медленнее, чем диски EIDE для операций записи, и гораздо быстрее их в случае выполнения операций чтения). Одним из очень важных свойств флеш-памяти, различные варианты которого будут рассмотрены далее в этой статье, является то, что каждый сектор имеет ограниченные возможности по перезаписыванию. Вы можете только записывать, стирать и снова записывать на сектор флеш-памяти определенное количество раз до того, как сектор станет полностью неработоспособным. Хотя многие продукты на основе флеш-памяти автоматически перенаправляют испорченные блоки, а некоторые даже распределяют операции записи по всему модулю, фактом является наличие ограничения на количество операций записи, которые могут выполняться с устройством. Современные модули имеют характеристики от 1,000,000 до 10,000,000 циклов записи на сектор. Эти характеристики могут зависеть от температуры рабочей среды.
+Эта статья будет ограничиваться рассмотрением твердотельных дисковых устройств, которые делаются на основе флеш-памяти. Флеш-память является твердотельным (здесь нет движущихся частей) запоминающим устройством, которое является энергонезависимым (данные остаются в памяти даже после отключения всех источников питания). Флеш-память может быть нечувствительной к сильным физическим воздействиям и достаточно быстра (решения на основе флеш-памяти, описываемые в этой статье, гораздо медленнее, чем диски EIDE для операций записи, и гораздо быстрее их в случае выполнения операций чтения). Одним из очень важных свойств флеш-памяти, различные варианты которого будут рассмотрены далее в этой статье, является то, что каждый сектор имеет ограниченные возможности по перезаписыванию. Вы можете только записывать, стирать и снова записывать на сектор флеш-памяти определённое количество раз до того, как сектор станет полностью неработоспособным. Хотя многие продукты на основе флеш-памяти автоматически перенаправляют испорченные блоки, а некоторые даже распределяют операции записи по всему модулю, фактом является наличие ограничения на количество операций записи, которые могут выполняться с устройством. Современные модули имеют характеристики от 1,000,000 до 10,000,000 циклов записи на сектор. Эти характеристики могут зависеть от температуры рабочей среды.
В частности, мы обсудим компактные модули флеш-памяти, совместимые со стандартом ATA, которые стали весьма популярными в качестве носителя данных для цифровых камер. Особый интерес представляет тот факт, что они соответствуют шине IDE по контактам и совместимы с набором команд ATA. Таким образом, при помощи очень простого и дешевого адаптера такие устройства могут подключаться непосредственно к шине IDE компьютера. Если поступить таким образом, то такие операционные системы, как FreeBSD, распознают диск как обычный винчестер (весьма маленький).
@@ -68,7 +68,7 @@
Для тех, кто создает встраиваемую систему FreeBSD, интерес представляют несколько параметров ядра.
-Все встраиваемые системы FreeBSD, которые используют флеш-память в качестве системного диска, заинтересованы в использовании дисков в памяти и файловых систем в памяти. Из-за ограниченного количества циклов записи, которые можно выполнить с флеш-памятью, диск и файловые системы на нем будут, скорее всего, монтироваться в режиме доступа только для чтения. В таком случае файловые системы типа [.filename]#/tmp# и [.filename]#/var# монтируются как файловые системы в памяти для того, чтобы позволить системе создать журналы и обновить счетчики и временные файлы. Файловые системы в памяти являются критическим компонентом успешной работы FreeBSD на твердотельных устройствах.
+Все встраиваемые системы FreeBSD, которые используют флеш-память в качестве системного диска, заинтересованы в использовании дисков в памяти и файловых систем в памяти. Из-за ограниченного количества циклов записи, которые можно выполнить с флеш-памятью, диск и файловые системы на нём будут, скорее всего, монтироваться в режиме доступа только для чтения. В таком случае файловые системы типа [.filename]#/tmp# и [.filename]#/var# монтируются как файловые системы в памяти для того, чтобы позволить системе создать журналы и обновить счетчики и временные файлы. Файловые системы в памяти являются критическим компонентом успешной работы FreeBSD на твердотельных устройствах.
Вы должны удостовериться, что в конфигурационном файле вашего ядра присутствуют следующие строки:
@@ -82,7 +82,7 @@
Инициализация встраиваемой системы FreeBSD после загрузки управляется [.filename]#/etc/rc.initdiskless#.
-[.filename]#/etc/rc.d/var# монтирует [.filename]#/var# как файловую систему в памяти, создает указываемый список каталогов в [.filename]#/var# при помощи команды man:mkdir[1], изменяет режимы доступа на некоторые из этих каталогов. В процессе выполнения [.filename]#/etc/rc.d/var# задействуется еще одна переменная [.filename]#rc.conf# - `varsize`. Скрипт [.filename]#/etc/rc.d/var# создает раздел [.filename]#/var# на основе значения этой переменной из [.filename]#rc.conf#:
+[.filename]#/etc/rc.d/var# монтирует [.filename]#/var# как файловую систему в памяти, создает указываемый список каталогов в [.filename]#/var# при помощи команды man:mkdir[1], изменяет режимы доступа на некоторые из этих каталогов. В процессе выполнения [.filename]#/etc/rc.d/var# задействуется ещё одна переменная [.filename]#rc.conf# - `varsize`. Скрипт [.filename]#/etc/rc.d/var# создает раздел [.filename]#/var# на основе значения этой переменной из [.filename]#rc.conf#:
[.programlisting]
....
@@ -117,17 +117,17 @@
== Создание файловой системы с нуля
-Так как совместимые с ATA компактные флеш-карты распознаются во FreeBSD как обычные жесткие диски IDE, то теоретически вы можете установить FreeBSD по сети при помощи дискет kern и mfsroot или с компакт-диска.
+Так как совместимые с ATA компактные флеш-карты распознаются во FreeBSD как обычные жёсткие диски IDE, то теоретически вы можете установить FreeBSD по сети при помощи дискет kern и mfsroot или с компакт-диска.
Однако даже маленькая установка FreeBSD при помощи обычных процедур установки может привести к созданию системы размером, превышающим 200 мегабайт. Так как большинство людей используют устройства флеш-памяти меньшего размера (128 мегабайт считается весьма большим - 32 или даже 16 мегабайт используются гораздо чаще), то установка обычным образом не подходит-просто на диске нет места даже для самой минимальной установки.
-Самым простым способом обойти это ограничение на объем является установка FreeBSD обычным образом на обычный жесткий диск. После окончания установки, обрежьте операционную систему до размера, который помещается на ваш флеш-носитель, а затем полностью заархивируйте файловую систему. Следующие шаги поведут вас через процесс подготовки части флеш-памяти для вашей заархивированной файловой системы. Запомните, что из-за того, что обычная установка не выполнялась, такие операции, как разбиение на разделы, разметка, создание файловой системы и так далее должны быть выполнены вручную. Кроме дискет kern и mfsroot вам также нужно воспользоваться дискетой fixit.
+Самым простым способом обойти это ограничение на объём является установка FreeBSD обычным образом на обычный жёсткий диск. После окончания установки, обрежьте операционную систему до размера, который помещается на ваш флеш-носитель, а затем полностью заархивируйте файловую систему. Следующие шаги поведут вас через процесс подготовки части флеш-памяти для вашей заархивированной файловой системы. Запомните, что из-за того, что обычная установка не выполнялась, такие операции, как разбиение на разделы, разметка, создание файловой системы и так далее должны быть выполнены вручную. Кроме дискет kern и mfsroot вам также нужно воспользоваться дискетой fixit.
[.procedure]
====
. Разбиение вашего флеш-носителя на разделы
+
-После загрузки при помощи дискет kern и mfsroot, выберите пункт `custom` из меню установки. Из следующего пункта меню выберите `partition`. В меню работы с разделами вы должны удалить все существующие разделы при помощи клавиши kbd:[d]. После удаления всех имеющихся разделов создайте раздел при помощи клавиши kbd:[c] и согласитесь с предлагаемым по умолчанию размером раздела. Когда вы будете опрошены на предмет типа раздела, удостоверьтесь, что значение типа равно `165`. Теперь запишите эту таблицу разделов на диск, нажав клавишу kbd:[w] (на этом экране эта опция скрыта). Если вы используете компактную флеш-карту, совместимую с ATA, вы должны выбрать FreeBSD Boot Manager. Теперь нажмите клавишу kbd:[q] для выхода из меню работы с разделами. Должно быть выдано еще раз меню для выбора менеджера загрузки - повторите то, что вы выбирали ранее.
+После загрузки при помощи дискет kern и mfsroot, выберите пункт `custom` из меню установки. Из следующего пункта меню выберите `partition`. В меню работы с разделами вы должны удалить все существующие разделы при помощи клавиши kbd:[d]. После удаления всех имеющихся разделов создайте раздел при помощи клавиши kbd:[c] и согласитесь с предлагаемым по умолчанию размером раздела. Когда вы будете опрошены на предмет типа раздела, удостоверьтесь, что значение типа равно `165`. Теперь запишите эту таблицу разделов на диск, нажав клавишу kbd:[w] (на этом экране эта опция скрыта). Если вы используете компактную флеш-карту, совместимую с ATA, вы должны выбрать FreeBSD Boot Manager. Теперь нажмите клавишу kbd:[q] для выхода из меню работы с разделами. Должно быть выдано ещё раз меню для выбора менеджера загрузки - повторите то, что вы выбирали ранее.
. Создание файловых систем на вашем устройстве флеш-памяти
+
Выйдите из меню установки custom, и из главного меню установки выберите пункт `fixit`. После входа в режим работы fixit, введите следующую команду:
@@ -169,7 +169,7 @@
# route add default 192.168.0.1
....
+
-Теперь, когда машина находится в сети, перепишите ваш tar-файл. Здесь вы можете столкнуться с некоторой проблемой - если объем вашей флеш-памяти равен, к примеру, 128 мегабайтам, а ваш tar-файл превышает 64 мегабайта, то вы не можете одновременно разместить tar-файл на флеш-носителе и распаковать его - вам не хватит места. Одним из решений этой проблемы, если вы используете FTP, является распаковка файла во время его передачи по FTP. Если вы передаёте файл именно так, то вы никогда не получите на диске одновременно архивный файл и его содержимое:
+Теперь, когда машина находится в сети, перепишите ваш tar-файл. Здесь вы можете столкнуться с некоторой проблемой - если объём вашей флеш-памяти равен, к примеру, 128 мегабайтам, а ваш tar-файл превышает 64 мегабайта, то вы не можете одновременно разместить tar-файл на флеш-носителе и распаковать его - вам не хватит места. Одним из решений этой проблемы, если вы используете FTP, является распаковка файла во время его передачи по FTP. Если вы передаёте файл именно так, то вы никогда не получите на диске одновременно архивный файл и его содержимое:
+
[source, shell]
....
@@ -202,7 +202,7 @@
=== Cron
-Во время загрузки содержимое каталогa [.filename]#/var# формируется скриптом [.filename]#/etc/rc.d/var# используя данные из [.filename]#/etc/mtree/BSD.var.dist#, поэтому в нем создается несколько стандартных каталогов, в числе которых - [.filename]#cron#, [.filename]#cron/tabs#, [.filename]#at#.
+Во время загрузки содержимое каталогa [.filename]#/var# формируется скриптом [.filename]#/etc/rc.d/var# используя данные из [.filename]#/etc/mtree/BSD.var.dist#, поэтому в нём создается несколько стандартных каталогов, в числе которых - [.filename]#cron#, [.filename]#cron/tabs#, [.filename]#at#.
Однако это не решает проблему с сохранением cron-таблиц между перезагрузками. Когда система перезагружается, то файловая система [.filename]#/var#, которая располагается в памяти, будет уничтожена, вместе со всеми cron-таблицами, которые вы могли там иметь. Поэтому одним из решений может стать создание cron-таблиц для пользователей, которым они нужны, монтирование вашей файловой системы [.filename]#/# в режиме чтения и записи, и копирование этих cron-таблиц в безопасное место, например, в [.filename]#/etc/tabs#, и последующее добавление строки в конец скрипта [.filename]#/etc/rc.initdiskless# для копирования этих cron-таблиц в каталог [.filename]#/var/cron/tabs# после его создания во время инициализации системы. Вам может также потребоваться добавить строку, которая изменяет режимы доступа и права на каталоги, которые вы создали, и на файлы, которые вы скопировали в скрипте [.filename]#/etc/rc.initdiskless#.
-По сравнению с зеркалированием, `RAID-5` имеет преимущество в виде значительно меньшего требуемого объема хранилища. Скорость чтения аналогична таковой при чередующейся организации, но скорость записи значительно ниже — примерно 25% от скорости чтения. Если один диск выходит из строя, массив может продолжать работу в деградировавшем режиме, при котором чтение с оставшихся доступных дисков продолжается в обычном режиме, а чтение с отказавшего диска пересчитывается из соответствующих блоков всех оставшихся дисков.
+По сравнению с зеркалированием, `RAID-5` имеет преимущество в виде значительно меньшего требуемого объёма хранилища. Скорость чтения аналогична таковой при чередующейся организации, но скорость записи значительно ниже — примерно 25% от скорости чтения. Если один диск выходит из строя, массив может продолжать работу в деградировавшем режиме, при котором чтение с оставшихся доступных дисков продолжается в обычном режиме, а чтение с отказавшего диска пересчитывается из соответствующих блоков всех оставшихся дисков.
[[vinum-objects]]
== Объекты [.filename]#vinum#
@@ -132,7 +132,7 @@
Следующие разделы статьи описывают, каким образом эти объекты обеспечивают функциональность, требуемую для [.filename]#vinum#.
-=== Учет размера томов
+=== Учёт размера томов
Плексы могут включать несколько поддисков, распределенных по всем дискам в конфигурации [.filename]#vinum#. В результате, размер отдельного диска не ограничивает размер плекса или тома.
@@ -573,7 +573,7 @@
Можно заметить, что параметр `size` для поддельного раздела `a` совпадает с указанным выше значением, в то время как параметр `offset` представляет собой сумму смещения внутри раздела [.filename]#vinum# `h` и смещения этого раздела в устройстве или слайсе. Это стандартная настройка, необходимая для избежания проблемы, описанной в crossref:vinum[vinum-root-panic, Nothing Boots, the Bootstrap Panics]. Весь раздел `a` полностью находится внутри раздела `h`, содержащего все данные [.filename]#vinum# для этого устройства.
-В приведенном выше примере все устройство выделено под [.filename]#vinum#, и не осталось корневого раздела, существовавшего до [.filename]#vinum#.
+В приведённом выше примере все устройство выделено под [.filename]#vinum#, и не осталось корневого раздела, существовавшего до [.filename]#vinum#.
=== Устранение неполадок
@@ -583,7 +583,7 @@
Если по какой-либо причине система не продолжает загрузку, процесс можно прервать, нажав kbd:[space] при появлении 10-секундного предупреждения. Переменную загрузчика `vinum.autostart` можно проверить, введя команду `show`, и изменить с помощью `set` или `unset`.
-Если модуль ядра [.filename]#vinum# еще не был в списке модулей для автоматической загрузки, введите `load geom_vinum`.
+Если модуль ядра [.filename]#vinum# ещё не был в списке модулей для автоматической загрузки, введите `load geom_vinum`.
Когда всё готово, процесс загрузки можно продолжить, введя `boot -as`, где `-as` указывает ядру запросить корневую файловую систему для монтирования (`-a`) и остановить процесс загрузки в однопользовательском режиме (`-s`), при этом корневая файловая система монтируется в режиме только для чтения. Таким образом, даже если смонтирован только один слой многокомпонентного тома, не возникает риска несогласованности данных между слоями.
-Перед тем, как перейти непосредственно к существующей архитектуре, потратим немного времени на рассмотрение вопроса о необходимости поддержки и модернизации любого длительно живущего кода. В мире программирования алгоритмы становятся более важными, чем код, и именно из-за академических корней BSD изначально большое внимание уделялось проработке алгоритмов. Внимание, уделенное архитектуре, в общем отражается на ясности и гибкости кода, который может быть достаточно легко изменен, расширен или с течением времени заменен. Хотя некоторые считают BSD "старой" операционной системой, те их нас, кто работает над ней, видят ее скорее системой со "зрелым" кодом с различными компонентами, которые были заменены, расширены или изменены современным кодом. Он развивается, и FreeBSD остается передовой системой, вне зависимости от того, насколько старой может быть часть кода. Это важное отличие, которое, к сожалению, не всеми понимается. Самой большой ошибкой, которую может допустить программист, является игнорирование истории, и это именно та ошибка, которую сделали многие другие современные операционные системы. Самым ярки примером здесь является Windows NT(R), и последствия ужасны. Linux также в некоторой степени совершил эту ошибку-достаточно, чтобы мы, люди BSD, по крайней мере по разу отпустили по этому поводу шутку. Проблема Linux заключается просто в отсутствии опыта и истории для сравнения идей, проблема, которая легко и быстро решается сообществом Linux точно так же, как она решается в сообществе BSD-постоянной работой над кодом. Разработчики Windows NT(R), с другой стороны, постоянно совершают те же самые ошибки, что были решены в UNIX(R) десятки лет назад, а затем тратят годы на их устранение. Снова и снова. Есть несколько случаев "проработка архитектуры отсутствует" и "мы всегда правы, потому что так говорит наш отдел продаж". Я плохо переношу тех, кого не учит история.
+Перед тем, как перейти непосредственно к существующей архитектуре, потратим немного времени на рассмотрение вопроса о необходимости поддержки и модернизации любого длительно живущего кода. В мире программирования алгоритмы становятся более важными, чем код, и именно из-за академических корней BSD изначально большое внимание уделялось проработке алгоритмов. Внимание, уделенное архитектуре, в общем отражается на ясности и гибкости кода, который может быть достаточно легко изменен, расширен или с течением времени заменен. Хотя некоторые считают BSD "старой" операционной системой, те их нас, кто работает над ней, видят её скорее системой со "зрелым" кодом с различными компонентами, которые были заменены, расширены или изменены современным кодом. Он развивается, и FreeBSD остается передовой системой, вне зависимости от того, насколько старой может быть часть кода. Это важное отличие, которое, к сожалению, не всеми понимается. Самой большой ошибкой, которую может допустить программист, является игнорирование истории, и это именно та ошибка, которую сделали многие другие современные операционные системы. Самым ярки примером здесь является Windows NT(R), и последствия ужасны. Linux также в некоторой степени совершил эту ошибку-достаточно, чтобы мы, люди BSD, по крайней мере по разу отпустили по этому поводу шутку. Проблема Linux заключается просто в отсутствии опыта и истории для сравнения идей, проблема, которая легко и быстро решается сообществом Linux точно так же, как она решается в сообществе BSD-постоянной работой над кодом. Разработчики Windows NT(R), с другой стороны, постоянно совершают те же самые ошибки, что были решены в UNIX(R) десятки лет назад, а затем тратят годы на их устранение. Снова и снова. Есть несколько случаев "проработка архитектуры отсутствует" и "мы всегда правы, потому что так говорит наш отдел продаж". Я плохо переношу тех, кого не учит история.
Большинство очевидной сложности архитектуры FreeBSD, особенно в подсистеме VM/Swap, является прямым следствием того, что она решает серьезные проблемы с производительностью, которые проявляются при различных условиях. Эти проблемы вызваны не плохой проработкой алгоритмов, а возникают из окружающих факторов. В любом прямом сравнении между платформами эти проблемы проявляются, когда системные ресурсы начинают истощаться. Так как я описываю подсистему VM/Swap во FreeBSD, то читатель должен всегда иметь в виду два обстоятельства:
-. Самым важным аспектом при проектировании производительности является то, что называется "оптимизацией критического маршрута". Часто случается, что оптимизация производительности дает прирост объема кода ради того, чтобы критический маршрут работал быстрее.
+. Самым важным аспектом при проектировании производительности является то, что называется "оптимизацией критического маршрута". Часто случается, что оптимизация производительности дает прирост объёма кода ради того, чтобы критический маршрут работал быстрее.
. Четкость общей архитектуры оказывается лучше сильно оптимизированной архитектуры с течением времени. Когда как обобщенная архитектура может быть медленнее, чем оптимизированная архитектура, при первой реализации, при обобщенной архитектуре легче подстраиваться под изменяющиеся условия и чрезмерно оптимизированная архитектура оказывается непригодной.
Любой код, который должен выжить и поддаваться поддержке годы, должен поэтому быть тщательно продуман с самого начала, даже если это стоит потери производительности. Двадцать лет назад были те, кто отстаивал преимущество программирования на языке ассемблера перед программированием на языке высокого уровня, потому что первый генерировал в десять раз более быстрый код. В наши дни ошибочность этого аргумента очевидна - можно провести параллели с построением алгоритмов и обобщением кода.
@@ -71,11 +71,11 @@
[[vm-objects]]
== Объекты VM
-Лучше всего начать описание VM-системы FreeBSD с попытки взглянуть на нее с точки зрения пользовательского процесса. Каждый пользовательский процесс имеет единое, принадлежащее только ему и неразрывное адресное пространство VM, содержащее несколько типов объектов памяти. Эти объекты имеют различные характеристики. Код программы и ее данные являются единым файлом, отображаемым в память (это выполняющийся двоичный файл), однако код программы доступен только для чтения, когда как данные программы размещаются в режиме копирования-при-записи. BSS программы представляет собой всего лишь выделенную область памяти, заполненную, если это требовалось, нулями, что называется обнулением страниц памяти по требованию. Отдельные файлы могут также отображаться в адресное пространство, именно так работают динамические библиотеки. Такие отображения требуют изменений, чтобы оставаться принадлежащими процессу, который их выполнил. Системный вызов fork добавляет переводит проблему управления VM полностью в новую плоскость, вдобавок к уже имеющимся сложностям.
+Лучше всего начать описание VM-системы FreeBSD с попытки взглянуть на нее с точки зрения пользовательского процесса. Каждый пользовательский процесс имеет единое, принадлежащее только ему и неразрывное адресное пространство VM, содержащее несколько типов объектов памяти. Эти объекты имеют различные характеристики. Код программы и её данные являются единым файлом, отображаемым в память (это выполняющийся двоичный файл), однако код программы доступен только для чтения, когда как данные программы размещаются в режиме копирования-при-записи. BSS программы представляет собой всего лишь выделенную область памяти, заполненную, если это требовалось, нулями, что называется обнулением страниц памяти по требованию. Отдельные файлы могут также отображаться в адресное пространство, именно так работают динамические библиотеки. Такие отображения требуют изменений, чтобы оставаться принадлежащими процессу, который их выполнил. Системный вызов fork добавляет переводит проблему управления VM полностью в новую плоскость, вдобавок к уже имеющимся сложностям.
-Иллюстрирует сложность страница данных двоичной программы (которая является страницей копируемой-при-записи). Двоичная программа содержит секцию предварительно инициализированных данных, которая первоначально отображается непосредственно из файла программы. Когда программа загружается в Vm-пространство процесса, эта область сначала отображается в память и поддерживается бинарным файлом программы, позволяя VM-системе освобождать/повторно использовать страницу, а потом загружать ее снова из бинарного файла. Однако в момент, когда процесс изменяет эти данные, VM-система должна сделать копию страницы, принадлежащую только этому процессу. Так как эта копия была изменена, то VM-система не может больше освобождать эту страницу, так как впоследствии ее невозможно будет восстановить.
+Иллюстрирует сложность страница данных двоичной программы (которая является страницей копируемой-при-записи). Двоичная программа содержит секцию предварительно инициализированных данных, которая первоначально отображается непосредственно из файла программы. Когда программа загружается в Vm-пространство процесса, эта область сначала отображается в память и поддерживается бинарным файлом программы, позволяя VM-системе освобождать/повторно использовать страницу, а потом загружать её снова из бинарного файла. Однако в момент, когда процесс изменяет эти данные, VM-система должна сделать копию страницы, принадлежащую только этому процессу. Так как эта копия была изменена, то VM-система не может больше освобождать эту страницу, так как впоследствии её невозможно будет восстановить.
-Вы тут же заметите, что то, что сначала было простым отображением файла в память, становится гораздо более сложным предметом. Данные могут модифицироваться постранично, когда как отображение файла выполняется для многих страниц за раз. Сложность еще более увеличивается, когда процесс выполняет вызов fork. При этом порождаются два процесса-каждый со с собственным адресным пространством, включающим все изменения, выполненные исходным процессом до вызова функции `fork()`. Было бы глупо для VM-системы делать полную копию данных во время вызова `fork()`, так как весьма вероятно, что один из двух процессов будет нужен только для чтения из той страницы, что позволяет использование исходной страницы. То, что было страницей, принадлежащей только процессу, сделается снова страницей, копируемой при записи, так как каждый из процессов (и родитель, и потомок) полагают, что их собственные изменения после разветвления будут принадлежать только им, и не затронут родственный процесс.
+Вы тут же заметите, что то, что сначала было простым отображением файла в память, становится гораздо более сложным предметом. Данные могут модифицироваться постранично, когда как отображение файла выполняется для многих страниц за раз. Сложность ещё более увеличивается, когда процесс выполняет вызов fork. При этом порождаются два процесса-каждый со с собственным адресным пространством, включающим все изменения, выполненные исходным процессом до вызова функции `fork()`. Было бы глупо для VM-системы делать полную копию данных во время вызова `fork()`, так как весьма вероятно, что один из двух процессов будет нужен только для чтения из той страницы, что позволяет использование исходной страницы. То, что было страницей, принадлежащей только процессу, сделается снова страницей, копируемой при записи, так как каждый из процессов (и родитель, и потомок) полагают, что их собственные изменения после разветвления будут принадлежать только им, и не затронут родственный процесс.
FreeBSD управляет всем этим при помощи многоуровневой модели VM-объектов. Исходный файл с двоичной программой переносится на самый нижний уровень объектов VM. Уровень страниц, копируемых при записи, находится выше него, и хранит те страницы, которые были скопированы из исходного файла. Если программа модифицирует страницы данных, относящиеся к исходному файлу, то система VM обнаруживает это и переносит копию этой страницы на более высокий уровень. Когда процесс разветвляется, добавляются новые уровни VM-объектов. Это можно показать на простом примере. Функция `fork()` является общей операцией для всех систем *BSD, так что в этом примере будет рассматриваться программа, которая запускается, а затем разветвляется. Когда процесс запускается, VM-система создает некоторый уровень объектов, обозначим его A:
@@ -95,23 +95,23 @@
В этом случае количество потомков B становится равным одному и все обращения к B теперь выполняются через C1. Это означает, что B и C1 могут быть объединены. Все страницы в B, которые также существуют и в C1, во время объединения из B удаляются. Таким образом, хотя оптимизация на предыдущем шаге может не делаться, мы можем восстановить мертвые страницы при окончании работы процессов или при вызове `exec()`.
-Такая модель создает некоторое количество потенциальных проблем. Первая, с которой вы можете столкнуться, заключается в сравнительно большой последовательности уровней объектов VM, на сканирование которых тратится время и память. Большое количество уровней может возникнуть, когда процессы разветвляются, а затем разветвляются еще раз (как порожденные, так и порождающие). Вторая проблема заключается в том, что вы можете столкнуться с мертвыми, недоступными страницами глубоко в иерархии объектов VM. В нашем последнем примере если как родитель, так и потомок изменяют одну и ту же страницу, они оба получают собственные копии страницы, а исходная страница в B становится никому не доступной. такая страница в B может быть высвобождена.
+Такая модель создает некоторое количество потенциальных проблем. Первая, с которой вы можете столкнуться, заключается в сравнительно большой последовательности уровней объектов VM, на сканирование которых тратится время и память. Большое количество уровней может возникнуть, когда процессы разветвляются, а затем разветвляются ещё раз (как порожденные, так и порождающие). Вторая проблема заключается в том, что вы можете столкнуться с мертвыми, недоступными страницами глубоко в иерархии объектов VM. В нашем последнем примере если как родитель, так и потомок изменяют одну и ту же страницу, они оба получают собственные копии страницы, а исходная страница в B становится никому не доступной. такая страница в B может быть высвобождена.
FreeBSD решает проблему с глубиной вложенности с помощью приема оптимизации, который называется "All Shadowed Case". Этот случай возникает, если в C1 либо C2 возникает столько случаев копирования страниц при записи, что они полностью закрывают все страницы в B. Допустим, что такое произошло в C1. C1 может теперь полностью заменить B, так что вместо цепочек C1->B->A и C2->B->A мы теперь имеем цепочки C1->A и C2->B->A. Но посмотрите, что получается-теперь B имеет только одну ссылку (C2), так что мы можем объединить B и C2. В конечном итоге B будет полностью удален и мы имеем цепочки C1->A и C2->A. Часто B будет содержать большое количество страниц, и ни C1, ни C2 не смогут полностью их заменить. Если мы снова породим процесс и создадим набор уровней D, при этом, однако, более вероятно, что один из уровней D постепенно сможет полностью заместить гораздо меньший набор данных, представленный C1 и C2. Та же самая оптимизация будет работать в любой точке графа и главным результатом этого является то, что даже на сильно загруженной машине с множеством порождаемых процессов стеки объектов VM не часто бывают глубже четырех уровней. Это так как для порождающего, так и для порожденного процессов, и остается в силе как в случае, когда ветвление делает родитель, так и в случае, когда ветвление выполняет потомок.
-Проблема с мертвой страницей все еще имеет место, когда C1 или C2 не полностью перекрывают B. Из-за других применяемых нами методов оптимизации этот случай не представляет большой проблемы и мы просто позволяем таким страницам существовать. Если система испытывает нехватку оперативной памяти, она выполняет их выгрузку в область подкачки, что занимает некоторое пространство в области подкачки, но это все.
+Проблема с мертвой страницей все ещё имеет место, когда C1 или C2 не полностью перекрывают B. Из-за других применяемых нами методов оптимизации этот случай не представляет большой проблемы и мы просто позволяем таким страницам существовать. Если система испытывает нехватку оперативной памяти, она выполняет их выгрузку в область подкачки, что занимает некоторое пространство в области подкачки, но это все.
Преимущество модели VM-объектов заключается в очень быстром выполнении функции `fork()`, так как при этом не выполняется реального копирования данных. Минусом этого подхода является то, что вы можете построить сравнительно сложную иерархию объектов VM, которая несколько замедляет обработку ситуаций отсутствия страниц памяти, и к тому же тратится память на управление структурами объектов VM. Приемы оптимизации, применяемые во FreeBSD, позволяют снизить значимость этих проблем до степени, когда их можно без особых потерь игнорировать.
[[swap-layers]]
== Уровни области подкачки
-Страницы с собственными данными первоначально являются страницами, копируемыми при записи или заполняемыми нулями. Когда выполняется изменение, и, соответственно, копирование, начальное хранилище объекта (обычно файл) не может больше использоваться для хранения копии страницы, когда VM-системе нужно использовать ее повторно для других целей. В этот момент на помощь приходит область подкачки. Область подкачки выделяется для организации хранилища памяти, которая иначе не может быть доступна. FreeBSD создает структуру управления подкачкой для объекта VM, только когда это действительно нужно. Однако структура управления подкачкой исторически имела некоторые проблемы:
+Страницы с собственными данными первоначально являются страницами, копируемыми при записи или заполняемыми нулями. Когда выполняется изменение, и, соответственно, копирование, начальное хранилище объекта (обычно файл) не может больше использоваться для хранения копии страницы, когда VM-системе нужно использовать её повторно для других целей. В этот момент на помощь приходит область подкачки. Область подкачки выделяется для организации хранилища памяти, которая иначе не может быть доступна. FreeBSD создает структуру управления подкачкой для объекта VM, только когда это действительно нужно. Однако структура управления подкачкой исторически имела некоторые проблемы:
-* Во FreeBSD 3.X в структуре управления областью подкачки предварительно выделяется массив, который представляет целый объект, требующий хранения в области подкачки-даже если только несколько страниц этого объекта хранятся в области подкачки. Это создает проблему фрагментации памяти ядра в случае, когда в память отображаются большие объекты или когда ветвятся процессы, занимающие большой объем памяти при работе (RSS).
-* Также для отслеживания памяти подкачки в памяти ядра поддерживается "список дыр", и он также несколько фрагментирован. Так как "список дыр" является последовательным списком, то производительность при распределении и высвобождении памяти в области подкачки неоптимально и ее сложность зависит от количества страниц как O(n).
+* Во FreeBSD 3.X в структуре управления областью подкачки предварительно выделяется массив, который представляет целый объект, требующий хранения в области подкачки-даже если только несколько страниц этого объекта хранятся в области подкачки. Это создает проблему фрагментации памяти ядра в случае, когда в память отображаются большие объекты или когда ветвятся процессы, занимающие большой объём памяти при работе (RSS).
+* Также для отслеживания памяти подкачки в памяти ядра поддерживается "список дыр", и он также несколько фрагментирован. Так как "список дыр" является последовательным списком, то производительность при распределении и высвобождении памяти в области подкачки неоптимально и её сложность зависит от количества страниц как O(n).
* Также в процессе высвобождения памяти в области подкачки требуется выделение памяти в ядре, и это приводит к проблемам блокировки при недостатке памяти.
-* Проблема еще более обостряется из-за дыр, создаваемых по чередующемуся алгоритму.
+* Проблема ещё более обостряется из-за дыр, создаваемых по чередующемуся алгоритму.
* Кроме того, список распределения блоков в области подкачки легко оказывается фрагментированным, что приводит к распределению непоследовательных областей.
* Память ядра также должна распределяться по ходу работы для дополнительных структур по управлению областью подкачки при выгрузке страниц памяти в эту область.
@@ -119,7 +119,7 @@
* Структуры управления областью подкачки распределяются при помощи хэш-таблицы, а не через линейный массив, что дает им фиксированный размер при распределении и работу с гораздо меньшими структурами.
* Вместо того, чтобы использовать однонаправленный связный список для отслеживания выделения пространства в области подкачки, теперь используется побитовая карта блоков области подкачки, выполненная в основном в виде древовидной структуры с информацией о свободном пространстве, находящейся в узлах структур. Это приводит к тому, что выделение и высвобождение памяти в области подкачки становится операцией сложности O(1).
-* Все дерево также распределяется заранее для того, чтобы избежать распределения памяти ядра во время операций с областью подкачки при критически малом объеме свободной памяти. В конце концов, система обращается к области подкачки при нехватке памяти, так что мы должны избежать распределения памяти ядра в такие моменты для избежания потенциальных блокировок.
+* Все дерево также распределяется заранее для того, чтобы избежать распределения памяти ядра во время операций с областью подкачки при критически малом объёме свободной памяти. В конце концов, система обращается к области подкачки при нехватке памяти, так что мы должны избежать распределения памяти ядра в такие моменты для избежания потенциальных блокировок.
* Для уменьшения фрагментации дерево может распределять большой последовательный кусок за раз, пропуская меньшие фрагментированные области.
Я не сделал последний шаг к заведению "указателя на распределение", который будет передвигаться по участку области подкачки при выделении памяти для обеспечения в будущем распределения последовательных участков, или по крайней мере местоположения ссылки, но я убежден, что это может быть сделано.
@@ -135,9 +135,9 @@
В любом случае, бит использования страницы очищается, и в некоторый более поздний момент VM-система обращается к странице снова и обнаруживает, что этот бит установлен. Это указывает на то, что страница активно используется. Периодически проверяя этот бит, накапливается история использования (в виде счетчика) физической страницы. Когда позже VM-системе требуется высвободить некоторые страницы, проверка истории выступает указателем при определении наиболее вероятной кандидатуры для повторного использования.
-Для тех платформ, что не имеют этой возможности, система эмулирует этот бит. Она снимает отображение или защищает страницу, что приводит к ошибке доступа к странице, если к странице выполняется повторное обращение. При возникновении этой ошибки система просто помечает страницу как используемую и снимает защиту со страницы, так что она может использоваться. Хотя использование такого приема только для определения использования страницы весьма накладно, это выгоднее, чем повторно использовать страницу для других целей и обнаружить, что она снова нужна процессу и подгружать ее с диска.
+Для тех платформ, что не имеют этой возможности, система эмулирует этот бит. Она снимает отображение или защищает страницу, что приводит к ошибке доступа к странице, если к странице выполняется повторное обращение. При возникновении этой ошибки система просто помечает страницу как используемую и снимает защиту со страницы, так что она может использоваться. Хотя использование такого приема только для определения использования страницы весьма накладно, это выгоднее, чем повторно использовать страницу для других целей и обнаружить, что она снова нужна процессу и подгружать её с диска.
-FreeBSD использует несколько очередей страниц для обновления выбора страниц для повторного использования, а также для определения того, когда же грязные страницы должны быть сброшены в хранилище. Так как таблицы страниц во FreeBSD являются динамическими объектами, практически ничего не стоит вырезать страницу из адресного пространства любого использующего ее процесса. После того, как подходящая страница, на основе счетчика использования, выбрана, именно это и выполняется. Система должна отличать между чистыми страницами, которые теоретически могут быть высвобождены в любое время, и грязными страницами, которые сначала должны быть переписаны в хранилище перед тем, как их можно будет использовать повторно. После нахождения подходящей страницы она перемещается в неактивную очередь, если она является грязной, или в очередь кэша, если она чистая. Отдельный алгоритм, основывающийся на отношении количества грязных страниц к чистым, определяет, когда грязные страницы в неактивной очереди должны быть сброшены на диск. Когда это выполнится, сброшенные страницы перемещаются из неактивной очереди в очередь кэша. В этот момент страницы в очереди кэша могут быть повторно активизированы VM со сравнительно малыми накладными расходами. Однако страницы в очереди кэша предполагается "высвобождать немедленно" и повторно использовать в LRU-порядке (меньше всего используемый), когда системе потребуется выделение дополнительной памяти.
+FreeBSD использует несколько очередей страниц для обновления выбора страниц для повторного использования, а также для определения того, когда же грязные страницы должны быть сброшены в хранилище. Так как таблицы страниц во FreeBSD являются динамическими объектами, практически ничего не стоит вырезать страницу из адресного пространства любого использующего её процесса. После того, как подходящая страница, на основе счетчика использования, выбрана, именно это и выполняется. Система должна отличать между чистыми страницами, которые теоретически могут быть высвобождены в любое время, и грязными страницами, которые сначала должны быть переписаны в хранилище перед тем, как их можно будет использовать повторно. После нахождения подходящей страницы она перемещается в неактивную очередь, если она является грязной, или в очередь кэша, если она чистая. Отдельный алгоритм, основывающийся на отношении количества грязных страниц к чистым, определяет, когда грязные страницы в неактивной очереди должны быть сброшены на диск. Когда это выполнится, сброшенные страницы перемещаются из неактивной очереди в очередь кэша. В этот момент страницы в очереди кэша могут быть повторно активизированы VM со сравнительно малыми накладными расходами. Однако страницы в очереди кэша предполагается "высвобождать немедленно" и повторно использовать в LRU-порядке (меньше всего используемый), когда системе потребуется выделение дополнительной памяти.
Стоит отметить, что во FreeBSD VM-система пытается разделить чистые и грязные страницы во избежание срочной необходимости в ненужных сбросах грязных страниц (что отражается на пропускной способности ввода/вывода) и не перемещает беспричинно страницы между разными очередями, когда подсистема управления памятью не испытывает нехватку ресурсов. Вот почему вы можете видеть, что при выполнении команды `systat -vm` в некоторых системах значение счетчика очереди кэша мало, а счетчик активной очереди большой. При повышении нагрузки на VM-систему она прилагает большие усилия на поддержку различных очередей страниц в соотношениях, которые являются наиболее эффективными.
@@ -146,9 +146,9 @@
[[prefault-optimizations]]
== Оптимизация ошибок доступа к страницам и их обнуления
-Полагая, что ошибка доступа к странице памяти в VM не является операцией с большими накладными расходами, если страница уже находится в основной памяти и может быть просто отображена в адресное пространство процесса, может оказаться, что это станет весьма накладно, если их будет оказываться регулярно много. Хорошим примером этой ситуации является запуск таких программ, как man:ls[1] или man:ps[1], снова и снова. Если бинарный файл программы отображен в память, но не отображен в таблицу страниц, то все страницы, к которым обращалась программа, окажутся недоступными при каждом запуске программы. Это не так уж необходимо, если эти страницы уже присутствуют в кэше VM, так что FreeBSD будет пытаться восстанавливать таблицы страниц процесса из тех страниц, что уже располагаются в VM-кэше. Однако во FreeBSD пока не выполняется предварительное копирование при записи определенных страниц при выполнении вызова exec. Например, если вы запускаете программу man:ls[1] одновременно с работающей `vmstat 1`, то заметите, что она всегда выдает некоторое количество ошибок доступа к страницам, даже когда вы запускаете ее снова и снова. Это ошибки заполнения нулями, а не ошибки кода программы (которые уже были обработаны). Предварительное копирование страниц при выполнении вызовов exec или fork находятся в области, требующей более тщательного изучения.
+Полагая, что ошибка доступа к странице памяти в VM не является операцией с большими накладными расходами, если страница уже находится в основной памяти и может быть просто отображена в адресное пространство процесса, может оказаться, что это станет весьма накладно, если их будет оказываться регулярно много. Хорошим примером этой ситуации является запуск таких программ, как man:ls[1] или man:ps[1], снова и снова. Если бинарный файл программы отображен в память, но не отображен в таблицу страниц, то все страницы, к которым обращалась программа, окажутся недоступными при каждом запуске программы. Это не так уж необходимо, если эти страницы уже присутствуют в кэше VM, так что FreeBSD будет пытаться восстанавливать таблицы страниц процесса из тех страниц, что уже располагаются в VM-кэше. Однако во FreeBSD пока не выполняется предварительное копирование при записи определённых страниц при выполнении вызова exec. Например, если вы запускаете программу man:ls[1] одновременно с работающей `vmstat 1`, то заметите, что она всегда выдает некоторое количество ошибок доступа к страницам, даже когда вы запускаете её снова и снова. Это ошибки заполнения нулями, а не ошибки кода программы (которые уже были обработаны). Предварительное копирование страниц при выполнении вызовов exec или fork находятся в области, требующей более тщательного изучения.
-Большой процент ошибок доступа к страницам, относится к ошибкам при заполнении нулями. Вы можете обычно видеть это, просматривая вывод команды `vmstat -s`. Это происходит, когда процесс обращается к страницам в своей области BSS. Область BSS предполагается изначально заполненной нулями, но VM-система не заботится о выделении памяти до тех пор, пока процесс реально к ней не обратится. При возникновении ошибки VM-система должна не только выделить новую страницу, но и заполнить ее нулями. Для оптимизации операции по заполнению нулями в системе VM имеется возможность предварительно обнулять страницы и помечать их, и запрашивать уже обнуленные страницы при возникновении ошибок заполнения нулями. Предварительное заполнение нулями происходит, когда CPU простаивает, однако количество страниц, которые система заранее заполняет нулями, ограничено, для того, чтобы не переполнить кэши памяти. Это прекрасный пример добавления сложности в VM-систему ради оптимизации критического пути.
+Большой процент ошибок доступа к страницам, относится к ошибкам при заполнении нулями. Вы можете обычно видеть это, просматривая вывод команды `vmstat -s`. Это происходит, когда процесс обращается к страницам в своей области BSS. Область BSS предполагается изначально заполненной нулями, но VM-система не заботится о выделении памяти до тех пор, пока процесс реально к ней не обратится. При возникновении ошибки VM-система должна не только выделить новую страницу, но и заполнить её нулями. Для оптимизации операции по заполнению нулями в системе VM имеется возможность предварительно обнулять страницы и помечать их, и запрашивать уже обнуленные страницы при возникновении ошибок заполнения нулями. Предварительное заполнение нулями происходит, когда CPU простаивает, однако количество страниц, которые система заранее заполняет нулями, ограничено, для того, чтобы не переполнить кэши памяти. Это прекрасный пример добавления сложности в VM-систему ради оптимизации критического пути.
[[page-table-optimizations]]
== Оптимизация таблицы страниц
@@ -173,7 +173,7 @@
A B C D A B C D A B C D A B C D
....
-FreeBSD 3.X использует "последовательный список свободных областей" для управления свободными областями в разделе подкачки. Идея состоит в том, что большие последовательные блоки свободного пространства могут быть представлены при помощи узла односвязного списка ([.filename]#kern/subr_rlist.c#). Но из-за фрагментации последовательный список сам становится фрагментированным. В примере выше полностью неиспользуемое пространство в A и B будет показано как "свободное", а C и D как "полностью занятое". Каждой последовательности A-B требуется для учета узел списка, потому что C и D являются дырами, так что узел списка не может быть связан со следующей последовательностью A-B.
+FreeBSD 3.X использует "последовательный список свободных областей" для управления свободными областями в разделе подкачки. Идея состоит в том, что большие последовательные блоки свободного пространства могут быть представлены при помощи узла односвязного списка ([.filename]#kern/subr_rlist.c#). Но из-за фрагментации последовательный список сам становится фрагментированным. В примере выше полностью неиспользуемое пространство в A и B будет показано как "свободное", а C и D как "полностью занятое". Каждой последовательности A-B требуется для учёта узел списка, потому что C и D являются дырами, так что узел списка не может быть связан со следующей последовательностью A-B.
Почему мы организуем чередование в области подкачки вместо того, чтобы просто объединить области подкачки в одно целое и придумать что-то более умное? Потому что гораздо легче выделять последовательные полосы адресного пространства и получать в результате автоматическое чередование между несколькими дисками, чем пытаться выдумывать сложности в другом месте.
@@ -189,18 +189,18 @@
=== В примере с / vmstat 1 могут ли некоторые ошибки доступа к странице быть ошибками страниц данных (COW из выполнимого файла в приватные страницы)? То есть я полагаю, что ошибки доступа к страницам являются частично ошибками при заполнении нулями, а частично данных программы. Или вы гарантируете, что FreeBSD выполняет предварительно COW для данных программы?
-Ошибка COW может быть ошибкой при заполнении нулями или данных программы. Механизм в любом случае один и тот же, потому что хранилище данных программы уже в кэше. Я на самом деле не рад ни тому, ни другому. FreeBSD не выполняет предварительное COW данных программы и заполнение нулями, но она _выполняет_ предварительно отображение страниц, которые имеются в ее кэше.
+Ошибка COW может быть ошибкой при заполнении нулями или данных программы. Механизм в любом случае один и тот же, потому что хранилище данных программы уже в кэше. Я на самом деле не рад ни тому, ни другому. FreeBSD не выполняет предварительное COW данных программы и заполнение нулями, но она _выполняет_ предварительно отображение страниц, которые имеются в её кэше.
=== В вашем разделе об оптимизации таблицы страниц, не могли бы вы более подробно рассказать о pv_entry и vm_page (или vm_page должна быть vm_pmap-как в 4.4, cf. pp. 180-181 of McKusick, Bostic, Karel, Quarterman)? А именно какое действие/реакцию должно потребоваться для сканирования отображений?
`vm_page` представляет собой пару (object,index#). `pv_entry` является записью из аппаратной таблицы страниц (pte). Если у вас имеется пять процессов, совместно использующих одну и ту же физическую страницу, и в трех таблицах страниц этих процессов на самом деле отображается страница, то страница будет представляться одной структурой `vm_page` и тремя структурами `pv_entry`.
-Структуры `pv_entry` представляют страницы, отображаемые MMU (одна структура `pv_entry` соответствует одной pte). Это означает, что, когда нам нужно убрать все аппаратные ссылки на `vm_page` (для того, чтобы повторно использовать страницу для чего-то еще, выгрузить ее, очистить, пометить как грязную и так далее), мы можем просто просмотреть связный список структур `pv_entry`, связанных с этой `vm_page`, для того, чтобы удалить или изменить pte из их таблиц страниц.
+Структуры `pv_entry` представляют страницы, отображаемые MMU (одна структура `pv_entry` соответствует одной pte). Это означает, что, когда нам нужно убрать все аппаратные ссылки на `vm_page` (для того, чтобы повторно использовать страницу для чего-то ещё, выгрузить её, очистить, пометить как грязную и так далее), мы можем просто просмотреть связный список структур `pv_entry`, связанных с этой `vm_page`, для того, чтобы удалить или изменить pte из их таблиц страниц.
В Linux нет такого связного списка. Для того, чтобы удалить все отображения аппаратной таблицы страниц для `vm_page`, linux должен пройти по индексу каждого объекта VM, который _может_ отображать страницу. К примеру, если у вас имеется 50 процессов, которые все отображают ту же самую динамическую библиотеку и хотите избавиться от страницы X в этой библиотеке, то вам нужно пройтись по индексу всей таблицы страниц для каждого из этих 50 процессов, даже если только 10 из них на самом деле отображают страницу. Так что Linux использует простоту подхода за счет производительности. Многие алгоритмы VM, которые имеют сложность O(1) или (N малое) во FreeBSD, в Linux приобретают сложность O(N), O(N^2) или хуже. Так как pte, представляющий конкретную страницу в объекте, скорее всего, будет с тем же смещением во всех таблицах страниц, в которых они отображаются, то уменьшение количества обращений в таблицы страниц по тому же самому смещению часто позволяет избежать разрастания кэша L1 для этого смещения, что приводит к улучшению производительности.
Во FreeBSD введены дополнительные сложности (схема с `pv_entry`) для увеличения производительности (уменьшая количество обращений _только_ к тем pte, которые нужно модифицировать).
-Но во FreeBSD имеется проблема масштабирования, которой нет в Linux, потому что имеется ограниченное число структур `pv_entry`, и это приводит к возникновению проблем при большом объеме совместно используемых данных. В этом случае у вас может возникнуть нехватка структур `pv_entry`, даже если свободной памяти хватает. Это может быть достаточно легко исправлено увеличением количества структур `pv_entry` при настройке, но на самом деле нам нужно найти лучший способ делать это.
+Но во FreeBSD имеется проблема масштабирования, которой нет в Linux, потому что имеется ограниченное число структур `pv_entry`, и это приводит к возникновению проблем при большом объёме совместно используемых данных. В этом случае у вас может возникнуть нехватка структур `pv_entry`, даже если свободной памяти хватает. Это может быть достаточно легко исправлено увеличением количества структур `pv_entry` при настройке, но на самом деле нам нужно найти лучший способ делать это.
Что касается использования памяти под таблицу страниц против схемы с `pv_entry`: Linux использует "постоянные" таблицы страниц, которые не сбрасываются, но ему не нужны `pv_entry` для каждого потенциально отображаемого pte. FreeBSD использует "сбрасываемые" таблицы страниц, но для каждого реально отображаемого pte добавляется структура `pv_entry`. Я думаю, что использование памяти будет примерно одинакова, тем более что у FreeBSD есть алгоритмическое преимущество, заключающееся в способности сбрасывать таблицы страниц с очень малыми накладными расходами.