diff --git a/documentation/content/ru/articles/geom-class/_index.adoc b/documentation/content/ru/articles/geom-class/_index.adoc index 58c72a91b3..22389f2b60 100644 --- a/documentation/content/ru/articles/geom-class/_index.adoc +++ b/documentation/content/ru/articles/geom-class/_index.adoc @@ -1,362 +1,362 @@ --- authors: - author: 'Ivan Voras' email: ivoras@FreeBSD.org description: 'Руководство по внутреннему устройству GEOM и созданию собственного класса GEOM' tags: ["GEOM", "kernel", "modules", "FreeBSD"] title: 'Создание класса GEOM' trademarks: ["freebsd", "intel", "general"] --- = Создание класса GEOM :doctype: article :toc: macro :toclevels: 1 :icons: font :sectnums: :sectnumlevels: 6 :source-highlighter: rouge :experimental: :images-path: articles/geom-class/ ifdef::env-beastie[] ifdef::backend-html5[] include::shared/authors.adoc[] include::shared/mirrors.adoc[] include::shared/releases.adoc[] include::shared/attributes/attributes-{{% lang %}}.adoc[] include::shared/{{% lang %}}/teams.adoc[] include::shared/{{% lang %}}/mailing-lists.adoc[] include::shared/{{% lang %}}/urls.adoc[] :imagesdir: ../../../images/{images-path} endif::[] ifdef::backend-pdf,backend-epub3[] include::../../../../shared/asciidoctor.adoc[] endif::[] endif::[] ifndef::env-beastie[] include::../../../../../shared/asciidoctor.adoc[] endif::[] [.abstract-title] Аннотация Эта статья документирует некоторые начальные выкладки в разработке GEOM-классов, а также модулей ядра в общем. Предполагается, что читатель близко знаком с программированием на Си в контексте пространства пользовательских процессов (userland). ''' toc::[] [[intro]] == Введение [[intro-docs]] === Documentation Документация по программированию для ядра скудная, это одна из немногих областей программирования, где почти нет хороших учебных пособий, и совет "читай исходники!" - сохраняет свою справедливость. Однако, существует несколько статей и книг разной актуальности, которые рекомендуются к изучению перед тем, как начать программировать: * extref:{developers-handbook}[Руководство FreeBSD для разработчиков] - часть Проекта Документации FreeBSD, ничего специфичного о программировании ядра в нём нет, зато есть немного общей полезной информации. * extref:{arch-handbook}[Руководство по Архитектуре FreeBSD] - также является частью Проекта Документации FreeBSD, содержит описания некоторых низкоуровневых средств и процедур. Уделите внимание разделу номер 13 - extref:{arch-handbook}[Написание драйверов устройств для FreeBSD, driverbasics]. * Несколько интересных статей об устройстве ядра можно найти на сайте http://www.freebsddiary.com[FreeBSD Diary]. * Страницы из раздела номер 9 системного справочника, содержат важную документацию по функциям ядра. * Страница справочника man:geom[4], а также http://phk.freebsd.dk/pubs/[слайды Пола-Хеннинга Кампа ] - общее представление о подсистеме GEOM. * Страницы справочника man:g_bio[9], man:g_event[9], man:g_data[9], man:g_geom[9], man:g_provider[9], man:g_consumer[9], man:g_access[9], а также другие, связанные с вышеупомянутыми и раскрывающие специфический функционал подсистемы GEOM. * Страница справочника man:style[9] - документирует соглашения о стиле оформления кода, которые обязаны быть соблюдены если вы планируете передать ваш код в Subversion репозиторий FreeBSD. [[prelim]] == Подготовка Для того, чтоб заниматься разработками для ядра, желательно иметь два отдельных компьютера. Один из них предназначен для среды разработки и исходных кодов, а второй - для запуска тестов отлаживаемого кода. Второму компьютеру для работы достаточно иметь возможность выполнять начальную загрузку по сети и монтирование файловых систем по сети. В этой ситуации, если отлаживаемый код содержит ошибки и вызовет аварийную остановку системы, то это не повлечет порчу или утерю исходного кода . Второму компьютеру даже не потребуется иметь свой монитор, достаточно будет соединения асинхронных портов кабелем RS-232 или соединения при помощи KVM-устройства. Но так как далеко не у каждого есть два или более компьютеров под рукой, есть пара способов подготовить иную "живую" систему для разработки кода для ядра. Один из них - это разработка в http://www.vmware.com/[VMWare] или http://www.qemu.org/[QEmu] виртуальной машине (это лучшее из доступного, после, конечно-же, выделенного для тестов компьютера). [[prelim-system]] === Настройка системы для разработки Прежде всего необходимо иметь в ядре поддержку `INVARIANTS`. Добавьте следующие строки в файл конфигурации ядра: [.programlisting] .... options INVARIANT_SUPPORT options INVARIANTS .... Для большей информативности при отладке включите поддержку WITNESS, которая будет предупреждать вас в случае возникновения взаимоблокировок: [.programlisting] .... options WITNESS_SUPPORT options WITNESS .... Также включите отладочные символы, если планируете выполнять отладку по дампам аварийных отказов: [.programlisting] .... makeoptions DEBUG=-g .... Установка отладочного ядра обычным способом (`make installkernel`) не даст привычного результата: файл ядра будет называться [.filename]#kernel.debug# и будет находиться в [.filename]#/usr/obj/usr/src/sys/KERNELNAME/#. Для удобства, отладочное ядро необходимо скопировать в [.filename]#/boot/kernel/#. Также удобно иметь включенный отладчик ядра, так вы сможете исследовать паники сразу-же после их возникновения. Для включения отладчика добавьте следующие строки в файл конфигурации ядра: [.programlisting] .... options KDB options DDB options KDB_TRACE .... Для автоматического запуска отладчика ядра после возникновения паники может понадобиться установить переменную sysctl: [.programlisting] .... debug.debugger_on_panic=1 .... Паники системы будут происходить, поэтому уделите внимание кэшу файловой системы. Обычно, при включенном механизме softupdates, последняя версия файла может быть утеряна если паника произошла раньше сбрасывания кэша на устройство хранения. Выключение механизма softupdates (посредством монтирования файловой системы с опцией "sync") значительно сказывается на производительности и, опять-же, не гарантирует целостности данных. Как компромисс, можно сократить задержки сбрасывания кэша механизма softupdates. Есть три переменных sysctl, значения которых необходимо изменить (лучше всего - прописав их в [.filename]#/etc/sysctl.conf#): [.programlisting] .... kern.filedelay=5 kern.dirdelay=4 kern.metadelay=3 .... Значения этих переменных - секунды. Для отладки паник ядра необходимы дампы памяти. Так как паника ядра может "сломать" файловую систему, дамп сначала сохраняется в "сырой" раздел. Обычно, это своп-раздел. Поэтому, размер своп-раздела должен быть не меньше размера ОЗУ компьютера. При последующей загрузке дамп копируется в обычный файл. Это происходит сразу-же после проверки и монтирования файловых систем, но перед активированием раздела свопа. Такое поведение контролируется следующими переменными [.filename]#/etc/rc.conf#: [.programlisting] .... dumpdev="/dev/ad0s4b" dumpdir="/usr/core" .... Переменная `dumpdev` указывает на раздел подкачки, а `dumpdir` сообщает системе куда перемещать дамп ядра при следующей загрузке. Сохранение дампа ядра - процесс медленный, и, если у вашего компьютера много оперативной памяти (>256M) и если паники случаются часто, то ожидание сохранения дампов может начать раздражать (вспомним, что над дампом происходит две операции: сохранение в своп-файл и перемещение на файловую систему). В таком случае может оказаться удобным ограничивание объёма используемой системой памяти путем установки переменной в [.filename]#/boot/loader.conf#: [.programlisting] .... hw.physmem="256M" .... Если паники случаются часто и размер файловых систем большой (или же вы просто не доверяете softupdates и фоновой проверке файловых систем), рекомендуется отключить фоновую проверку файловых систем посредством установки переменной в [.filename]#/etc/rc.conf#: [.programlisting] .... background_fsck="NO" .... В этом случае файловые системы будут проверяться только при необходимости. Также заметьте, что в случае использования фоновой проверки, новая паника может случиться в то время, когда проверяются диски. Другими словами, наиболее безопасный способ - не иметь много локальных файловых систем, а использовать второй компьютер в качестве NFS-сервера. [[prelim-starting]] === Начало проекта Для написания нового класса GEOM необходимо создать подкаталог в любом доступном пользователю каталоге. Совсем не обязательно, чтоб ваш модуль изначально размещался в [.filename]#/usr/src#. [[prelim-makefile]] === Makefile Правилом хорошего тона является создание [.filename]#Makefile#-ов для каждого нетривиального проекта, примером которого конечно-же является создание модулей ядра. Создание [.filename]#Makefile# - дело не сложное благодаря исчерпывающему набору вспомогательных средств, предоставляемых системой. В вкратце, вот как должен выглядеть [.filename]#Makefile# для модуля ядра: [.programlisting] .... SRCS=g_journal.c KMOD=geom_journal .include .... Этот [.filename]#Makefile# (с измененными именами файлов) подойдет к любому модулю ядра. Класс GEOM может размещаться в одном единственном модуле ядра. Если для сборки вашего модуля требуется больше, чем один файл, то перечислите их имена, разделенные пробельными символами, в переменной `SRCS`. [[kernelprog]] == Программирование в ядре FreeBSD [[kernelprog-memalloc]] === Выделение памяти Прочитайте man:malloc[9] - выделение памяти лишь немного отличается от своего эквивалента, используемого в пространстве пользовательских процессов (userland). Наиболее приметно то, что `malloc`() и `free`() принимают дополнительные параметры, которые описаны в странице справочника. Тип "malloc_type" необходимо объявить в секции деклараций файла с исходным кодом, например: [.programlisting] .... static MALLOC_DEFINE(M_GJOURNAL, "gjournal data", "GEOM_JOURNAL Data"); .... Для того, чтобы можно было использовать этот макрос, необходимо включить следующие заголовочные файлы: [.filename]#sys/param.h#, [.filename]#sys/kernel.h# и [.filename]#sys/malloc.h#. Существует ещё один механизм выделения памяти - UMA (Universal Memory Allocator), описанный в man:uma[9]. Это специфический метод, преимущественно предназначенный для быстрого выделения памяти под списки, состоящие из элементов одинакового размера (например, динамические массивы структур). [[kernelprog-lists]] === Очереди и списки Ознакомьтесь с man:queue[3] Во множестве случаев вам необходимо будет организовывать и управлять такой структурой данных, как списки. К счастью, эта структура данных реализована несколькими способами в виде макросов на Си, а также включена в систему. Наиболее гибкий и часто употребляемый тип списка - TAILQ. Этот тип списка также один из наиболее требовательных к памяти (его элементы - с двойными связями), а также - наиболее медленный (однако счет идёт на несколько инструкций ЦПУ, поэтому последнее утверждение не следует воспринимать в всерьез). Если важна скорость получения данных, то возьмите на вооружение man:tree[3] и man:hashinit[9]. [[kernelprog-bios]] === BIOs Структура `bio` используется для всех операций ввода/вывода, касающихся GEOM. Она содержит информацию о том, какое устройство ('поставщик geom') должно ответить на запрос, тип запроса, смещение, длину и указатель на буфер, а также набор "определённых пользователем" флагов и полей . Важным моментом является то, что `bio` обрабатываются асинхронно. Это значит, что во многих частях кода нет аналога к man:read[2] и man:write[2] функциям из пространства пользовательских процессов, которые не возвращают управление пока не выполнится системный вызов. Скорее, по завершении обработки запроса (или в случае ошибки при обработке) как извещение вызывается определённая пользователем функция. Асинхронная модель программирования в чем-то сложней, нежели чаще используемая императивная модель, используемая в пространстве пользовательских процессов; в любом случае, привыкание займёт некоторое время. В некоторых случаях могут быть использованы вспомогательные функции `g_write_data`() и `g_read_data`(), но __далеко не всегда__. В частности, эти функции не могут использоваться когда захвачен мьютекс; например, мьютекс GEOM-топологии или внутренний мьютекс, удерживаемый в ходе выполнения `.start`() или `.stop`(). [[geom]] == Программирование в системе GEOM [[geom-ggate]] === Ggate Если максимальная производительность не требуется, то более простой способ совершать преобразования данных - это выполнять их в пространстве пользовательских процессов посредством ggate (GEOM gate). К недостаткам следует отнести невозможность простого переноса кода в ядро. [[geom-class]] === Класс GEOM Класс GEOM выполняет преобразования данных. Эти преобразования могут быть скомпонованы друг с другом в виде дерева. Экземпляр класса GEOM называют __geom__. В каждом классе GEOM есть несколько "методов класса", которые вызываются когда экземпляра класса нет в наличии (или же они не привязаны к конкретному экземпляру класса): * `.init` вызывается тогда, когда системе GEOM становится известно о классе GEOM (например, когда загружается модуль ядра). * `.fini` будет вызван в случае отказа GEOM системы от класса (например, при выгрузке модуля) -* `.taste` вызывается, когда в системе появляется новый класс или поставщик geom ("provider"). Если соответствие найдено, то эта функция обычно создает и запускает экземпляр geom. +* `.taste` вызывается, когда в системе появляется новый класс или поставщик geom ("provider"). Если соответствие найдено, то эта функция обычно создаёт и запускает экземпляр geom. * `.destroy_geom` вызывается при необходимости разрушить экземпляр geom * `.ctlconf` будет вызван, когда пользователь запросит изменение конфигурации существующего экземпляра geom Также определены функции событий GEOM, которые копируются в экземпляр geom. Поле `.geom` в структуре `g_class` - это список (LIST) экземпляров geom, реализованных из класса. Эти функции вызываются из g_event потока ядра. [[geom-softc]] === Softc "softc" - это устаревший термин для "приватных данных драйвера" ("driver private data"). Название вероятней всего происходит от устаревшего термина "software control block". В системе GEOM softc это структура (точнее: указатель на структуру) которая может быть присоединена к экземпляру geom и может содержать приватные данные экземпляра. У большинства классов GEOM есть следующие члены: * `struct g_provider *provider` : "поставщик geom" предоставляемый данным экземпляром geom * `uint16_t n_disks` : Количество потребителей geom ("consumer"), обслуживаемых данным экземпляром geom -* `struct g_consumer \**disks` : Массив `struct g_consumer*`. (Невозможно обойтись одинарным указателем, потому что система GEOM создает для нас структуры struct g_consumer). +* `struct g_consumer \**disks` : Массив `struct g_consumer*`. (Невозможно обойтись одинарным указателем, потому что система GEOM создаёт для нас структуры struct g_consumer). Структура `softc` содержит состояние экземпляра geom. У каждого экземпляра есть свой softc. [[geom-metadata]] === Метаданные Формат метаданных в той или иной мере зависит от конкретного класса, но _обязан_ начинаться с: * 16-байтного буфера для подписи - строки с завершающим нулем (обычно это имя класса) * uint32 идентификатора версии Подразумевается, что классы geom знают как обращаться с метаданными с идентификаторами версий ниже, чем их собственные. Метаданные размещаются в последнем секторе поставщика geom (поэтому обязаны целиком умещаться в нем). (Все это зависит от реализации, но весь существующий код работает подобно описанному и поддерживается библиотеками.) [[geom-creating]] === Маркирование/создание экземпляра geom Последовательность событий следующая: * пользователь запускает служебную программу man:geom[8] * программа решает каким классом geom ей придется управлять и ищет библиотеку [.filename]#geom_CLASSNAME.so# (которая обычно находится в [.filename]#/lib/geom#). * она открывает библиотеку при помощи man:dlopen[3], извлекает вспомогательные функции и определения параметров командной строки. Вот так происходит создание/маркирование нового экземпляра geom: * man:geom[8] ищет команду в аргументах командной строки (обычно это `label`) и вызывает вспомогательную функцию. * Вспомогательная функция проверяет параметры и собирает метаданные, которые записываются во все вовлеченные поставщики geom. * Это "повреждает (spoil)" существующие экземпляры geom (если они были) и порождает новый виток "тестирования" поставщиков geom. Целевой класс geom опознает метаданные и активирует экземпляр geom. (Приведенная выше последовательность событий зависит от конкретной реализации, но весь существующий код работает подобно описанному и поддерживается библиотеками.) [[geom-command]] === Структура команд geom Вспомогательная библиотека [.filename]#geom_CLASSNAME.so# экспортирует структуру `class_commands`, которая является массивом элементов `struct g_command`. Эти команды одинакового формата и выглядят следующим образом: [.programlisting] .... verb [-options] geomname [other] .... Общими командами являются: * label - записать метаданные в устройства, чтобы они могли быть опознаны в процессе тестирования и использованы в соответствующих экземплярах geom * destroy - разрушить метаданные, за которым последует разрушение экземпляров geom Общие опции: * `-v` : детальный вывод * `-f` : принудить Некоторые операции, к примеру маркирование метаданными и разрушение метаданных могут быть выполнены из пространства пользовательских процессов. Для этого, структура `g_command` содержит поле `gc_func`, которое может быть установлено на функцию (в том-же [.filename]#.so#), которая будет вызвана для обработки команды. В случае, когда `gc_func` равно NULL, команда будет передана модулю ядра: функции `.ctlreq` класса GEOM. [[geom-geoms]] === Экземпляры geom У экземпляров классов GEOM есть внутренние данные, которые хранятся в структурах softc, а также есть некоторые функции, посредством которых они реагируют на внешние события. Функции событий: * `.access` : просчитывает права доступа (чтение/запись/исключительный доступ) * `.dumpconf` : возвращает информацию о экземпляре geom; формат XML * `.orphan` : вызывается, когда отсоединяется любой из низлежащих поставщиков geom * `.spoiled` : вызывается, когда производится запись в низлежащий поставщик geom * `.start` : обрабатывает ввод/вывод Эти функции вызываются из ядерного потока `g_down` и в этом контексте не может быть блокировок (поищите определение "блокировка" в других источниках), что немного ограничивает свободу действий, но способствует быстроте обработки. Из вышеупомянутых, наиболее важной и выполняющей полезную работу функцией является `.start`(), которая вызывается всякий раз, когда поставщику geom, управляемому экземпляром класса, приходит запрос BIO. [[geom-threads]] === Потоки выполнения системы geom Системой GEOM в ядре ОС создаются и используются три потока выполнения (kernel threads): * `g_down` : Обрабатывает запросы, приходящие от высокоуровневых сущностей (таких как запросы из пространства пользовательских процессов) на пути к физическим устройствам * `g_up` : Обрабатывает ответы от драйверов устройств на запросы, выполненные высокоуровневыми сущностями * `g_event` : Отрабатывает в остальных случаях, как-то создание экземпляра geom, просчитывание прав доступа, события "повреждения" и т.п. Когда пользовательский процесс запрашивает "прочитать данные X по смещению Y файла", происходит следующее: * Файловая система преобразует запрос в экземпляр структуры bio и передаёт его системе GEOM. Файловая система "знает", что экземпляр geom должен обработать запрос, так как файловые системы размещаются непосредственно над экземпляром geom. * Запрос завершается вызовом функции `.start`() в потоке g_down и достигает верхнего экземпляра geom. -* Верхний экземпляр geom (например, это секционировщик разделов (partition slicer)) определяет, что запрос должен быть переадресован нижестоящему экземпляру geom (к примеру, драйверу диска). Вышестоящий экземпляр geom создает копию запроса bio (запросы bio _ВСЕГДА_ копируются при передаче между экземплярами geom при помощи `g_clone_bio`()!), изменяет поля смещения и целевого поставщика geom и запускает на обработку копию при помощи функции `g_io_request`() +* Верхний экземпляр geom (например, это секционировщик разделов (partition slicer)) определяет, что запрос должен быть переадресован нижестоящему экземпляру geom (к примеру, драйверу диска). Вышестоящий экземпляр geom создаёт копию запроса bio (запросы bio _ВСЕГДА_ копируются при передаче между экземплярами geom при помощи `g_clone_bio`()!), изменяет поля смещения и целевого поставщика geom и запускает на обработку копию при помощи функции `g_io_request`() * Драйвер диска также получает запрос bio, как вызов функции `.start`() в потоке `g_down`. Драйвер обращается к контроллеру диска, получает блок данных и вызывает функцию `g_io_deliver`() используя копию запроса bio. * Теперь, извещение о завершении bio "всплывает" в потоке `g_up`. Сначала в потоке `g_up` вызывается функция `.done`() секционировщика разделов, последний использует полученную информацию, разрушает клонированный экземпляр структуры bio посредством `g_destroy_bio`() и вызывает `g_io_deliver`() используя первоначальный запрос. * Файловая система получает данные и передаёт их пользовательскому процессу. За информацией о том, как данные передаются в структуре `bio` между экземплярами geom, смотрите man:g_bio[9] (обратите внимание на использование полей `bio_parent` и `bio_children`). Важный момент в том, что __НЕЛЬЗЯ ДОПУСКАТЬ БЛОКИРОВОК В ПОТОКАХ G_UP И G_DOWN__. Вот неполный перечень того, что нельзя делать в этих потоках: * Вызывать функции `msleep`() или `tsleep`(). * Использовать функции `g_write_data`() и `g_read_data`(), так как они блокируются в момент обмена данными с потребителями geom. * Ожидать ввод/вывод. * Вызывать man:malloc[9] и `uma_zalloc`() с установленным флагом `M_WAITOK` * Использовать man:sx[9] Это ограничение на код GEOM призвано избежать от "засорения" пути запроса ввода/вывода, так как блокировки обычно не имеют четких временных границ, и нет гарантий на занимаемое время (также на то есть и другие технические причины). Это также значит, что в вышеупомянутых потоках сколь-нибудь сложные операции выполнить нельзя, например: любое сложное преобразование требует выделения памяти. К счастью решение есть: создание дополнительных ядерных потоков. [[geom-kernelthreads]] === Ядерные потоки выполнения, предназначенные для использования в коде geom Ядерные потоки выполнения создаются функцией man:kthread_create[9], в своём поведении они схожи с потоками, созданными в пространстве пользовательских процессов, но есть одно отличие: они не могут известить вызвавший их поток о своём завершении; по завершению - необходимо вызывать man:kthread_exit[9]. В коде GEOM обычное назначение этих потоков - разгрузить поток `g_down` (функцию `.start`() ) от обработки запросов. Эти потоки подобны "обработчикам событий" ("event handlers"): у них есть очередь событий (которая наполняется событиями от разных функций из разных потоков; очередь необходимо защищать мьютексом), события из очереди выбираются одно за другим и обрабатываются в большом блоке `switch`(). Основное преимущество использования отдельного потока, который обрабатывает запросы ввода/вывода, то, что он может блокироваться по мере необходимости. Это, несомненно, привлекательно, но должно быть хорошо обдумано. Блокирование - хорошо и удобно, но может существенно снизить производительность преобразований данных в системе GEOM. Особо требовательные к производительности классы могут делать всю работу в функции `.start`(), уделяя особое внимание ошибкам при работе с памятью. Еще одно преимущество потока "обработчика событий" это сериализация всех запросов и ответов, приходящих с разных потоков geom в один поток. Это также удобно, но может быть медленным. В большинстве случаев, обработка запросов функцией `.done`() может быть оставлена потоку `g_up`. У мьютексов в ядре FreeBSD (man:mutex[9]) есть одно различие с их аналогами из пространства пользовательских процессов - во время удержания мьютекса в коде не должно быть блокировки. Если в коде необходимо блокирование, то лучше использовать man:sx[9]. С другой стороны, если вся ваша работа выполняется в одном потоке, вы можете обойтись вообще без мьютексов. diff --git a/documentation/content/ru/articles/geom-class/_index.po b/documentation/content/ru/articles/geom-class/_index.po index 073bbc1fe4..98c63ac300 100644 --- a/documentation/content/ru/articles/geom-class/_index.po +++ b/documentation/content/ru/articles/geom-class/_index.po @@ -1,1396 +1,1396 @@ # SOME DESCRIPTIVE TITLE # Copyright (C) YEAR The FreeBSD Project # This file is distributed under the same license as the FreeBSD Documentation package. # Vladlen Popolitov , 2025, 2026. msgid "" msgstr "" "Project-Id-Version: FreeBSD Documentation VERSION\n" -"POT-Creation-Date: 2026-03-15 14:39+0300\n" -"PO-Revision-Date: 2026-03-09 04:45+0000\n" +"POT-Creation-Date: 2026-05-11 14:38+0300\n" +"PO-Revision-Date: 2026-04-05 04:45+0000\n" "Last-Translator: Vladlen Popolitov \n" "Language-Team: Russian \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "X-Generator: Weblate 4.17\n" #. type: YAML Front Matter: description #: documentation/content/en/articles/geom-class/_index.adoc:1 #, no-wrap msgid "A guide to GEOM internals, and writing your own GEOM class" msgstr "Руководство по внутреннему устройству GEOM и созданию собственного класса GEOM" #. type: Title = #: documentation/content/en/articles/geom-class/_index.adoc:1 #: documentation/content/en/articles/geom-class/_index.adoc:11 #, no-wrap msgid "Writing a GEOM Class" msgstr "Создание класса GEOM" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:44 msgid "Abstract" msgstr "Аннотация" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:47 msgid "" "This text documents some starting points in developing GEOM classes, and " "kernel modules in general. It is assumed that the reader is familiar with C " "userland programming." msgstr "" "Эта статья документирует некоторые начальные выкладки в разработке GEOM-" "классов, а также модулей ядра в общем. Предполагается, что читатель близко " "знаком с программированием на Си в контексте пространства пользовательских " "процессов (userland)." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:49 msgid "'''" msgstr "'''" #. type: Title == #: documentation/content/en/articles/geom-class/_index.adoc:53 #, no-wrap msgid "Introduction" msgstr "Введение" #. type: Title === #: documentation/content/en/articles/geom-class/_index.adoc:56 #, no-wrap msgid "Documentation" msgstr "Documentation" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:60 msgid "" "Documentation on kernel programming is scarce - it is one of few areas where " "there is nearly nothing in the way of friendly tutorials, and the phrase " "\"use the source!\" really holds true. However, there are some bits and " "pieces (some of them seriously outdated) floating around that should be " "studied before beginning to code:" msgstr "" "Документация по программированию для ядра скудная, это одна из немногих " "областей программирования, где почти нет хороших учебных пособий, и совет " "\"читай исходники!\" - сохраняет свою справедливость. Однако, существует " "несколько статей и книг разной актуальности, которые рекомендуются к " "изучению перед тем, как начать программировать:" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:62 msgid "" "The extref:{developers-handbook}[FreeBSD Developer's Handbook] - part of the " "documentation project, it does not contain anything specific to kernel " "programming, but rather some general useful information." msgstr "" "extref:{developers-handbook}[Руководство FreeBSD для разработчиков] - часть " "Проекта Документации FreeBSD, ничего специфичного о программировании ядра в " "нём нет, зато есть немного общей полезной информации." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:63 msgid "" "The extref:{arch-handbook}[FreeBSD Architecture Handbook] - also from the " "documentation project, contains descriptions of several low-level facilities " "and procedures. The most important chapter is 13, extref:{arch-handbook}" "[Writing FreeBSD device drivers, driverbasics]." msgstr "" "extref:{arch-handbook}[Руководство по Архитектуре FreeBSD] - также является " "частью Проекта Документации FreeBSD, содержит описания некоторых " "низкоуровневых средств и процедур. Уделите внимание разделу номер 13 - " "extref:{arch-handbook}[Написание драйверов устройств для FreeBSD, " "driverbasics]." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:64 msgid "" "The Blueprints section of http://www.freebsddiary.org[FreeBSD Diary] web " "site - contains several interesting articles on kernel facilities." msgstr "" "Несколько интересных статей об устройстве ядра можно найти на сайте http://" "www.freebsddiary.com[FreeBSD Diary]." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:65 msgid "" "The man pages in section 9 - for important documentation on kernel functions." msgstr "" "Страницы из раздела номер 9 системного справочника, содержат важную " "документацию по функциям ядра." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:66 msgid "" "The man:geom[4] man page and http://phk.freebsd.dk/pubs/[PHK's GEOM slides] " "- for general introduction of the GEOM subsystem." msgstr "" "Страница справочника man:geom[4], а также http://phk.freebsd.dk/pubs/[слайды " "Пола-Хеннинга Кампа ] - общее представление о подсистеме GEOM." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:67 msgid "" "Man pages man:g_bio[9], man:g_event[9], man:g_data[9], man:g_geom[9], " "man:g_provider[9], man:g_consumer[9], man:g_access[9] & others linked from " "those, for documentation on specific functionalities." msgstr "" "Страницы справочника man:g_bio[9], man:g_event[9], man:g_data[9], " "man:g_geom[9], man:g_provider[9], man:g_consumer[9], man:g_access[9], а " "также другие, связанные с вышеупомянутыми и раскрывающие специфический " "функционал подсистемы GEOM." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:68 msgid "" "The man:style[9] man page - for documentation on the coding-style " "conventions which must be followed for any code which is to be committed to " "the FreeBSD tree." msgstr "" "Страница справочника man:style[9] - документирует соглашения о стиле " "оформления кода, которые обязаны быть соблюдены если вы планируете передать " "ваш код в Subversion репозиторий FreeBSD." #. type: Title == #: documentation/content/en/articles/geom-class/_index.adoc:70 #, no-wrap msgid "Preliminaries" msgstr "Подготовка" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:77 msgid "" "The best way to do kernel development is to have (at least) two separate " "computers. One of these would contain the development environment and " "sources, and the other would be used to test the newly written code by " "network-booting and network-mounting filesystems from the first one. This " "way if the new code contains bugs and crashes the machine, it will not mess " "up the sources (and other \"live\" data). The second system does not even " "require a proper display. Instead, it could be connected with a serial " "cable or KVM to the first one." msgstr "" "Для того, чтоб заниматься разработками для ядра, желательно иметь два " "отдельных компьютера. Один из них предназначен для среды разработки и " "исходных кодов, а второй - для запуска тестов отлаживаемого кода. Второму " "компьютеру для работы достаточно иметь возможность выполнять начальную " "загрузку по сети и монтирование файловых систем по сети. В этой ситуации, " "если отлаживаемый код содержит ошибки и вызовет аварийную остановку системы, " "то это не повлечет порчу или утерю исходного кода . Второму компьютеру даже " "не потребуется иметь свой монитор, достаточно будет соединения асинхронных " "портов кабелем RS-232 или соединения при помощи KVM-устройства." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:80 msgid "" "But, since not everybody has two or more computers handy, there are a few " "things that can be done to prepare an otherwise \"live\" system for " "developing kernel code. This setup is also applicable for developing in a " "http://www.vmware.com/[VMWare] or http://www.qemu.org/[QEmu] virtual machine " "(the next best thing after a dedicated development machine)." msgstr "" "Но так как далеко не у каждого есть два или более компьютеров под рукой, " "есть пара способов подготовить иную \"живую\" систему для разработки кода " "для ядра. Один из них - это разработка в http://www.vmware.com/[VMWare] или " "http://www.qemu.org/[QEmu] виртуальной машине (это лучшее из доступного, " "после, конечно-же, выделенного для тестов компьютера)." #. type: Title === #: documentation/content/en/articles/geom-class/_index.adoc:82 #, no-wrap msgid "Modifying a System for Development" msgstr "Настройка системы для разработки" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:85 msgid "" "For any kernel programming a kernel with `INVARIANTS` enabled is a must-" "have. So enter these in your kernel configuration file:" msgstr "" "Прежде всего необходимо иметь в ядре поддержку `INVARIANTS`. Добавьте " "следующие строки в файл конфигурации ядра:" #. type: delimited block . 4 #: documentation/content/en/articles/geom-class/_index.adoc:90 #, no-wrap msgid "" "options INVARIANT_SUPPORT\n" "options INVARIANTS\n" msgstr "" "options INVARIANT_SUPPORT\n" "options INVARIANTS\n" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:93 msgid "" "For more debugging you should also include WITNESS support, which will alert " "you of mistakes in locking:" msgstr "" "Для большей информативности при отладке включите поддержку WITNESS, которая " "будет предупреждать вас в случае возникновения взаимоблокировок:" #. type: delimited block . 4 #: documentation/content/en/articles/geom-class/_index.adoc:98 #, no-wrap msgid "" "options WITNESS_SUPPORT\n" "options WITNESS\n" msgstr "" "options WITNESS_SUPPORT\n" "options WITNESS\n" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:101 msgid "For debugging crash dumps, a kernel with debug symbols is needed:" msgstr "" "Также включите отладочные символы, если планируете выполнять отладку по " "дампам аварийных отказов:" #. type: delimited block . 4 #: documentation/content/en/articles/geom-class/_index.adoc:105 #, no-wrap msgid " makeoptions DEBUG=-g\n" msgstr " makeoptions DEBUG=-g\n" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:110 msgid "" "With the usual way of installing the kernel (`make installkernel`) the debug " "kernel will not be automatically installed. It is called " "[.filename]#kernel.debug# and located in [.filename]#/usr/obj/usr/src/sys/" "KERNELNAME/#. For convenience it should be copied to [.filename]#/boot/" "kernel/#." msgstr "" "Установка отладочного ядра обычным способом (`make installkernel`) не даст " "привычного результата: файл ядра будет называться [.filename]#kernel.debug# " "и будет находиться в [.filename]#/usr/obj/usr/src/sys/KERNELNAME/#. Для " "удобства, отладочное ядро необходимо скопировать в [.filename]#/boot/kernel/" "#." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:113 msgid "" "Another convenience is enabling the kernel debugger so you can examine a " "kernel panic when it happens. For this, enter the following lines in your " "kernel configuration file:" msgstr "" "Также удобно иметь включенный отладчик ядра, так вы сможете исследовать " "паники сразу-же после их возникновения. Для включения отладчика добавьте " "следующие строки в файл конфигурации ядра:" #. type: delimited block . 4 #: documentation/content/en/articles/geom-class/_index.adoc:119 #, no-wrap msgid "" "options KDB\n" "options DDB\n" "options KDB_TRACE\n" msgstr "" "options KDB\n" "options DDB\n" "options KDB_TRACE\n" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:122 msgid "" "For this to work you might need to set a sysctl (if it is not on by default):" msgstr "" "Для автоматического запуска отладчика ядра после возникновения паники может " "понадобиться установить переменную sysctl:" #. type: delimited block . 4 #: documentation/content/en/articles/geom-class/_index.adoc:126 #, no-wrap msgid " debug.debugger_on_panic=1\n" msgstr " debug.debugger_on_panic=1\n" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:134 msgid "" "Kernel panics will happen, so care should be taken with the filesystem " "cache. In particular, having softupdates might mean the latest file version " "could be lost if a panic occurs before it is committed to storage. " "Disabling softupdates yields a great performance hit, and still does not " "guarantee data consistency. Mounting filesystem with the \"sync\" option is " "needed for that. For a compromise, the softupdates cache delays can be " "shortened. There are three sysctl's that are useful for this (best to be " "set in [.filename]#/etc/sysctl.conf#):" msgstr "" "Паники системы будут происходить, поэтому уделите внимание кэшу файловой " "системы. Обычно, при включенном механизме softupdates, последняя версия " "файла может быть утеряна если паника произошла раньше сбрасывания кэша на " "устройство хранения. Выключение механизма softupdates (посредством " "монтирования файловой системы с опцией \"sync\") значительно сказывается на " "производительности и, опять-же, не гарантирует целостности данных. Как " "компромисс, можно сократить задержки сбрасывания кэша механизма softupdates. " "Есть три переменных sysctl, значения которых необходимо изменить (лучше " "всего - прописав их в [.filename]#/etc/sysctl.conf#):" #. type: delimited block . 4 #: documentation/content/en/articles/geom-class/_index.adoc:140 #, no-wrap msgid "" "kern.filedelay=5\n" "kern.dirdelay=4\n" "kern.metadelay=3\n" msgstr "" "kern.filedelay=5\n" "kern.dirdelay=4\n" "kern.metadelay=3\n" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:143 msgid "The numbers represent seconds." msgstr "Значения этих переменных - секунды." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:151 msgid "" "For debugging kernel panics, kernel core dumps are required. Since a kernel " "panic might make filesystems unusable, this crash dump is first written to a " "raw partition. Usually, this is the swap partition. This partition must be " "at least as large as the physical RAM in the machine. On the next boot, the " "dump is copied to a regular file. This happens after filesystems are " "checked and mounted, and before swap is enabled. This is controlled with " "two [.filename]#/etc/rc.conf# variables:" msgstr "" "Для отладки паник ядра необходимы дампы памяти. Так как паника ядра может " "\"сломать\" файловую систему, дамп сначала сохраняется в \"сырой\" раздел. " "Обычно, это своп-раздел. Поэтому, размер своп-раздела должен быть не меньше " "размера ОЗУ компьютера. При последующей загрузке дамп копируется в обычный " "файл. Это происходит сразу-же после проверки и монтирования файловых систем, " "но перед активированием раздела свопа. Такое поведение контролируется " "следующими переменными [.filename]#/etc/rc.conf#:" #. type: delimited block . 4 #: documentation/content/en/articles/geom-class/_index.adoc:156 #, no-wrap msgid "" "dumpdev=\"/dev/ad0s4b\"\n" "dumpdir=\"/usr/core\"\n" msgstr "" "dumpdev=\"/dev/ad0s4b\"\n" "dumpdir=\"/usr/core\"\n" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:159 msgid "" "The `dumpdev` variable specifies the swap partition and `dumpdir` tells the " "system where in the filesystem to relocate the core dump on reboot." msgstr "" "Переменная `dumpdev` указывает на раздел подкачки, а `dumpdir` сообщает " "системе куда перемещать дамп ядра при следующей загрузке." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:162 msgid "" "Writing kernel core dumps is slow and takes a long time so if you have lots " "of memory (>256M) and lots of panics it could be frustrating to sit and wait " "while it is done (twice - first to write it to swap, then to relocate it to " "filesystem). It is convenient then to limit the amount of RAM the system " "will use via a [.filename]#/boot/loader.conf# tunable:" msgstr "" "Сохранение дампа ядра - процесс медленный, и, если у вашего компьютера много " "оперативной памяти (>256M) и если паники случаются часто, то ожидание " "сохранения дампов может начать раздражать (вспомним, что над дампом " "происходит две операции: сохранение в своп-файл и перемещение на файловую " "систему). В таком случае может оказаться удобным ограничивание объёма " "используемой системой памяти путем установки переменной в [.filename]#/boot/" "loader.conf#:" #. type: delimited block . 4 #: documentation/content/en/articles/geom-class/_index.adoc:166 #, no-wrap msgid " hw.physmem=\"256M\"\n" msgstr " hw.physmem=\"256M\"\n" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:169 msgid "" "If the panics are frequent and filesystems large (or you simply do not trust " "softupdates+background fsck) it is advisable to turn background fsck off via " "[.filename]#/etc/rc.conf# variable:" msgstr "" "Если паники случаются часто и размер файловых систем большой (или же вы " "просто не доверяете softupdates и фоновой проверке файловых систем), " "рекомендуется отключить фоновую проверку файловых систем посредством " "установки переменной в [.filename]#/etc/rc.conf#:" #. type: delimited block . 4 #: documentation/content/en/articles/geom-class/_index.adoc:173 #, no-wrap msgid " background_fsck=\"NO\"\n" msgstr " background_fsck=\"NO\"\n" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:178 msgid "" "This way, the filesystems will always get checked when needed. Note that " "with background fsck, a new panic could happen while it is checking the " "disks. Again, the safest way is not to have many local filesystems by using " "another computer as an NFS server." msgstr "" "В этом случае файловые системы будут проверяться только при необходимости. " "Также заметьте, что в случае использования фоновой проверки, новая паника " "может случиться в то время, когда проверяются диски. Другими словами, " "наиболее безопасный способ - не иметь много локальных файловых систем, а " "использовать второй компьютер в качестве NFS-сервера." #. type: Title === #: documentation/content/en/articles/geom-class/_index.adoc:180 #, no-wrap msgid "Starting the Project" msgstr "Начало проекта" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:184 msgid "" "For the purpose of creating a new GEOM class, an empty subdirectory has to " "be created under an arbitrary user-accessible directory. You do not have to " "create the module directory under [.filename]#/usr/src#." msgstr "" "Для написания нового класса GEOM необходимо создать подкаталог в любом " "доступном пользователю каталоге. Совсем не обязательно, чтоб ваш модуль " "изначально размещался в [.filename]#/usr/src#." #. type: Title === #: documentation/content/en/articles/geom-class/_index.adoc:186 #, no-wrap msgid "The Makefile" msgstr "Makefile" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:189 msgid "" "It is good practice to create [.filename]#Makefiles# for every nontrivial " "coding project, which of course includes kernel modules." msgstr "" "Правилом хорошего тона является создание [.filename]#Makefile#-ов для " "каждого нетривиального проекта, примером которого конечно-же является " "создание модулей ядра." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:192 msgid "" "Creating the [.filename]#Makefile# is simple thanks to an extensive set of " "helper routines provided by the system. In short, here is how a minimal " "[.filename]#Makefile# looks for a kernel module:" msgstr "" "Создание [.filename]#Makefile# - дело не сложное благодаря исчерпывающему " "набору вспомогательных средств, предоставляемых системой. В вкратце, вот как " "должен выглядеть [.filename]#Makefile# для модуля ядра:" #. type: delimited block . 4 #: documentation/content/en/articles/geom-class/_index.adoc:197 #, no-wrap msgid "" "SRCS=g_journal.c\n" "KMOD=geom_journal\n" msgstr "" "SRCS=g_journal.c\n" "KMOD=geom_journal\n" #. type: delimited block . 4 #: documentation/content/en/articles/geom-class/_index.adoc:199 #, no-wrap msgid ".include \n" msgstr ".include \n" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:203 msgid "" "This [.filename]#Makefile# (with changed filenames) will do for any kernel " "module, and a GEOM class can reside in just one kernel module. If more than " "one file is required, list it in the `SRCS` variable, separated with " "whitespace from other filenames." msgstr "" "Этот [.filename]#Makefile# (с измененными именами файлов) подойдет к любому " "модулю ядра. Класс GEOM может размещаться в одном единственном модуле ядра. " "Если для сборки вашего модуля требуется больше, чем один файл, то " "перечислите их имена, разделенные пробельными символами, в переменной `SRCS`." #. type: Title == #: documentation/content/en/articles/geom-class/_index.adoc:205 #, no-wrap msgid "On FreeBSD Kernel Programming" msgstr "Программирование в ядре FreeBSD" #. type: Title === #: documentation/content/en/articles/geom-class/_index.adoc:208 #, no-wrap msgid "Memory Allocation" msgstr "Выделение памяти" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:213 msgid "" "See man:malloc[9]. Basic memory allocation is only slightly different than " "its userland equivalent. Most notably, `malloc`() and `free`() accept " "additional parameters as is described in the man page." msgstr "" "Прочитайте man:malloc[9] - выделение памяти лишь немного отличается от " "своего эквивалента, используемого в пространстве пользовательских процессов " "(userland). Наиболее приметно то, что `malloc`() и `free`() принимают " "дополнительные параметры, которые описаны в странице справочника." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:215 msgid "" "A \"malloc type\" must be declared in the declaration section of a source " "file, like this:" msgstr "" "Тип \"malloc_type\" необходимо объявить в секции деклараций файла с исходным " "кодом, например:" #. type: delimited block . 4 #: documentation/content/en/articles/geom-class/_index.adoc:219 #, no-wrap msgid " static MALLOC_DEFINE(M_GJOURNAL, \"gjournal data\", \"GEOM_JOURNAL Data\");\n" msgstr " static MALLOC_DEFINE(M_GJOURNAL, \"gjournal data\", \"GEOM_JOURNAL Data\");\n" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:222 msgid "" "To use this macro, [.filename]#sys/param.h#, [.filename]#sys/kernel.h# and " "[.filename]#sys/malloc.h# headers must be included." msgstr "" "Для того, чтобы можно было использовать этот макрос, необходимо включить " "следующие заголовочные файлы: [.filename]#sys/param.h#, [.filename]#sys/" "kernel.h# и [.filename]#sys/malloc.h#." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:225 msgid "" "There is another mechanism for allocating memory, the UMA (Universal Memory " "Allocator). See man:uma[9] for details, but it is a special type of " "allocator mainly used for speedy allocation of lists comprised of same-sized " "items (for example, dynamic arrays of structs)." msgstr "" "Существует ещё один механизм выделения памяти - UMA (Universal Memory " "Allocator), описанный в man:uma[9]. Это специфический метод, преимущественно " "предназначенный для быстрого выделения памяти под списки, состоящие из " "элементов одинакового размера (например, динамические массивы структур)." #. type: Title === #: documentation/content/en/articles/geom-class/_index.adoc:227 #, no-wrap msgid "Lists and Queues" msgstr "Очереди и списки" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:234 msgid "" "See man:queue[3]. There are a LOT of cases when a list of things needs to " "be maintained. Fortunately, this data structure is implemented (in several " "ways) by C macros included in the system. The most used list type is TAILQ " "because it is the most flexible. It is also the one with largest memory " "requirements (its elements are doubly-linked) and also the slowest (although " "the speed variation is on the order of several CPU instructions more, so it " "should not be taken seriously)." msgstr "" "Ознакомьтесь с man:queue[3] Во множестве случаев вам необходимо будет " "организовывать и управлять такой структурой данных, как списки. К счастью, " "эта структура данных реализована несколькими способами в виде макросов на " "Си, а также включена в систему. Наиболее гибкий и часто употребляемый тип " "списка - TAILQ. Этот тип списка также один из наиболее требовательных к " "памяти (его элементы - с двойными связями), а также - наиболее медленный " "(однако счет идёт на несколько инструкций ЦПУ, поэтому последнее утверждение " "не следует воспринимать в всерьез)." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:236 msgid "" "If data retrieval speed is very important, see man:tree[3] and " "man:hashinit[9]." msgstr "" "Если важна скорость получения данных, то возьмите на вооружение man:tree[3] " "и man:hashinit[9]." #. type: Title === #: documentation/content/en/articles/geom-class/_index.adoc:238 #, no-wrap msgid "BIOs" msgstr "BIOs" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:242 msgid "" "Structure `bio` is used for any and all Input/Output operations concerning " "GEOM. It basically contains information about what device ('provider') " "should satisfy the request, request type, offset, length, pointer to a " "buffer, and a bunch of \"user-specific\" flags and fields that can help " "implement various hacks." msgstr "" "Структура `bio` используется для всех операций ввода/вывода, касающихся " "GEOM. Она содержит информацию о том, какое устройство ('поставщик geom') " "должно ответить на запрос, тип запроса, смещение, длину и указатель на " "буфер, а также набор \"определённых пользователем\" флагов и полей ." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:246 msgid "" "The important thing here is that ``bio``s are handled asynchronously. That " "means that, in most parts of the code, there is no analogue to userland's " "man:read[2] and man:write[2] calls that do not return until a request is " "done. Rather, a developer-supplied function is called as a notification " "when the request gets completed (or results in error)." msgstr "" "Важным моментом является то, что `bio` обрабатываются асинхронно. Это " "значит, что во многих частях кода нет аналога к man:read[2] и man:write[2] " "функциям из пространства пользовательских процессов, которые не возвращают " "управление пока не выполнится системный вызов. Скорее, по завершении " "обработки запроса (или в случае ошибки при обработке) как извещение " "вызывается определённая пользователем функция." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:250 msgid "" "The asynchronous programming model (also called \"event-driven\") is " "somewhat harder than the much more used imperative one used in userland (at " "least it takes a while to get used to it). In some cases the helper " "routines `g_write_data`() and `g_read_data`() can be used, but __not " "always__. In particular, they cannot be used when a mutex is held; for " "example, the GEOM topology mutex or the internal mutex held during the " "`.start`() and `.stop`() functions." msgstr "" "Асинхронная модель программирования в чем-то сложней, нежели чаще " "используемая императивная модель, используемая в пространстве " "пользовательских процессов; в любом случае, привыкание займёт некоторое " "время. В некоторых случаях могут быть использованы вспомогательные функции " "`g_write_data`() и `g_read_data`(), но __далеко не всегда__. В частности, " "эти функции не могут использоваться когда захвачен мьютекс; например, " "мьютекс GEOM-топологии или внутренний мьютекс, удерживаемый в ходе " "выполнения `.start`() или `.stop`()." #. type: Title == #: documentation/content/en/articles/geom-class/_index.adoc:252 #, no-wrap msgid "On GEOM Programming" msgstr "Программирование в системе GEOM" #. type: Title === #: documentation/content/en/articles/geom-class/_index.adoc:255 #, no-wrap msgid "Ggate" msgstr "Ggate" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:259 msgid "" "If maximum performance is not needed, a much simpler way of making a data " "transformation is to implement it in userland via the ggate (GEOM gate) " "facility. Unfortunately, there is no easy way to convert between, or even " "share code between the two approaches." msgstr "" "Если максимальная производительность не требуется, то более простой способ " "совершать преобразования данных - это выполнять их в пространстве " "пользовательских процессов посредством ggate (GEOM gate). К недостаткам " "следует отнести невозможность простого переноса кода в ядро." #. type: Title === #: documentation/content/en/articles/geom-class/_index.adoc:261 #, no-wrap msgid "GEOM Class" msgstr "Класс GEOM" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:266 msgid "" "GEOM classes are transformations on the data. These transformations can be " "combined in a tree-like fashion. Instances of GEOM classes are called " "__geoms__." msgstr "" "Класс GEOM выполняет преобразования данных. Эти преобразования могут быть " "скомпонованы друг с другом в виде дерева. Экземпляр класса GEOM называют " "__geom__." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:268 msgid "" "Each GEOM class has several \"class methods\" that get called when there is " "no geom instance available (or they are simply not bound to a single " "instance):" msgstr "" "В каждом классе GEOM есть несколько \"методов класса\", которые вызываются " "когда экземпляра класса нет в наличии (или же они не привязаны к конкретному " "экземпляру класса):" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:270 msgid "" "`.init` is called when GEOM becomes aware of a GEOM class (when the kernel " "module gets loaded.)" msgstr "" "`.init` вызывается тогда, когда системе GEOM становится известно о классе " "GEOM (например, когда загружается модуль ядра)." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:271 msgid "" "`.fini` gets called when GEOM abandons the class (when the module gets " "unloaded)" msgstr "" "`.fini` будет вызван в случае отказа GEOM системы от класса (например, при " "выгрузке модуля)" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:272 msgid "" "`.taste` is called next, once for each provider the system has available. If " "applicable, this function will usually create and start a geom instance." msgstr "" "`.taste` вызывается, когда в системе появляется новый класс или поставщик " "geom (\"provider\"). Если соответствие найдено, то эта функция обычно " -"создает и запускает экземпляр geom." +"создаёт и запускает экземпляр geom." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:273 msgid "`.destroy_geom` is called when the geom should be disbanded" msgstr "`.destroy_geom` вызывается при необходимости разрушить экземпляр geom" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:274 msgid "" "`.ctlconf` is called when user requests reconfiguration of existing geom" msgstr "" "`.ctlconf` будет вызван, когда пользователь запросит изменение конфигурации " "существующего экземпляра geom" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:276 msgid "" "Also defined are the GEOM event functions, which will get copied to the geom " "instance." msgstr "" "Также определены функции событий GEOM, которые копируются в экземпляр geom." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:278 msgid "" "Field `.geom` in the `g_class` structure is a LIST of geoms instantiated " "from the class." msgstr "" "Поле `.geom` в структуре `g_class` - это список (LIST) экземпляров geom, " "реализованных из класса." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:280 msgid "These functions are called from the g_event kernel thread." msgstr "Эти функции вызываются из g_event потока ядра." #. type: Title === #: documentation/content/en/articles/geom-class/_index.adoc:282 #, no-wrap msgid "Softc" msgstr "Softc" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:288 msgid "" "The name \"softc\" is a legacy term for \"driver private data\". The name " "most probably comes from the archaic term \"software control block\". In " "GEOM, it is a structure (more precise: pointer to a structure) that can be " "attached to a geom instance to hold whatever data is private to the geom " "instance. Most GEOM classes have the following members:" msgstr "" "\"softc\" - это устаревший термин для \"приватных данных драйвера\" " "(\"driver private data\"). Название вероятней всего происходит от " "устаревшего термина \"software control block\". В системе GEOM softc это " "структура (точнее: указатель на структуру) которая может быть присоединена к " "экземпляру geom и может содержать приватные данные экземпляра. У большинства " "классов GEOM есть следующие члены:" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:290 msgid "`struct g_provider *provider` : The \"provider\" this geom instantiates" msgstr "" "`struct g_provider *provider` : \"поставщик geom\" предоставляемый данным " "экземпляром geom" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:291 msgid "`uint16_t n_disks` : Number of consumer this geom consumes" msgstr "" "`uint16_t n_disks` : Количество потребителей geom (\"consumer\"), " "обслуживаемых данным экземпляром geom" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:292 msgid "" "`struct g_consumer \\**disks` : Array of `struct g_consumer*`. (It is not " "possible to use just single indirection because struct g_consumer* are " "created on our behalf by GEOM)." msgstr "" "`struct g_consumer \\**disks` : Массив `struct g_consumer*`. (Невозможно " -"обойтись одинарным указателем, потому что система GEOM создает для нас " +"обойтись одинарным указателем, потому что система GEOM создаёт для нас " "структуры struct g_consumer)." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:295 msgid "" "The `softc` structure contains all the state of geom instance. Every geom " "instance has its own softc." msgstr "" "Структура `softc` содержит состояние экземпляра geom. У каждого экземпляра " "есть свой softc." #. type: Title === #: documentation/content/en/articles/geom-class/_index.adoc:297 #, no-wrap msgid "Metadata" msgstr "Метаданные" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:300 msgid "" "Format of metadata is more-or-less class-dependent, but MUST start with:" msgstr "" "Формат метаданных в той или иной мере зависит от конкретного класса, но " "_обязан_ начинаться с:" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:302 msgid "16 byte buffer for null-terminated signature (usually the class name)" msgstr "" "16-байтного буфера для подписи - строки с завершающим нулем (обычно это имя " "класса)" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:303 msgid "uint32 version ID" msgstr "uint32 идентификатора версии" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:305 msgid "" "It is assumed that geom classes know how to handle metadata with version " "ID's lower than theirs." msgstr "" "Подразумевается, что классы geom знают как обращаться с метаданными с " "идентификаторами версий ниже, чем их собственные." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:307 msgid "" "Metadata is located in the last sector of the provider (and thus must fit in " "it)." msgstr "" "Метаданные размещаются в последнем секторе поставщика geom (поэтому обязаны " "целиком умещаться в нем)." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:309 msgid "" "(All this is implementation-dependent but all existing code works like that, " "and it is supported by libraries.)" msgstr "" "(Все это зависит от реализации, но весь существующий код работает подобно " "описанному и поддерживается библиотеками.)" #. type: Title === #: documentation/content/en/articles/geom-class/_index.adoc:311 #, no-wrap msgid "Labeling/creating a GEOM" msgstr "Маркирование/создание экземпляра geom" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:314 msgid "The sequence of events is:" msgstr "Последовательность событий следующая:" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:316 msgid "user calls man:geom[8] utility (or one of its hardlinked friends)" msgstr "пользователь запускает служебную программу man:geom[8]" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:317 msgid "" "the utility figures out which geom class it is supposed to handle and " "searches for [.filename]#geom_CLASSNAME.so# library (usually in [.filename]#/" "lib/geom#)." msgstr "" "программа решает каким классом geom ей придется управлять и ищет библиотеку " "[.filename]#geom_CLASSNAME.so# (которая обычно находится в [.filename]#/lib/" "geom#)." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:318 msgid "" "it man:dlopen[3]-s the library, extracts the definitions of command-line " "parameters and helper functions." msgstr "" "она открывает библиотеку при помощи man:dlopen[3], извлекает вспомогательные " "функции и определения параметров командной строки." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:320 msgid "In the case of creating/labeling a new geom, this is what happens:" msgstr "Вот так происходит создание/маркирование нового экземпляра geom:" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:322 msgid "" "man:geom[8] looks in the command-line argument for the command (usually " "`label`), and calls a helper function." msgstr "" "man:geom[8] ищет команду в аргументах командной строки (обычно это `label`) " "и вызывает вспомогательную функцию." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:323 msgid "" "The helper function checks parameters and gathers metadata, which it " "proceeds to write to all concerned providers." msgstr "" "Вспомогательная функция проверяет параметры и собирает метаданные, которые " "записываются во все вовлеченные поставщики geom." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:324 msgid "" "This \"spoils\" existing geoms (if any) and initializes a new round of " "\"tasting\" of the providers. The intended geom class recognizes the " "metadata and brings the geom up." msgstr "" "Это \"повреждает (spoil)\" существующие экземпляры geom (если они были) и " "порождает новый виток \"тестирования\" поставщиков geom. Целевой класс geom " "опознает метаданные и активирует экземпляр geom." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:326 msgid "" "(The above sequence of events is implementation-dependent but all existing " "code works like that, and it is supported by libraries.)" msgstr "" "(Приведенная выше последовательность событий зависит от конкретной " "реализации, но весь существующий код работает подобно описанному и " "поддерживается библиотеками.)" #. type: Title === #: documentation/content/en/articles/geom-class/_index.adoc:328 #, no-wrap msgid "GEOM Command Structure" msgstr "Структура команд geom" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:332 msgid "" "The helper [.filename]#geom_CLASSNAME.so# library exports `class_commands` " "structure, which is an array of `struct g_command` elements. Commands are " "of uniform format and look like:" msgstr "" "Вспомогательная библиотека [.filename]#geom_CLASSNAME.so# экспортирует " "структуру `class_commands`, которая является массивом элементов `struct " "g_command`. Эти команды одинакового формата и выглядят следующим образом:" #. type: delimited block . 4 #: documentation/content/en/articles/geom-class/_index.adoc:336 #, no-wrap msgid " verb [-options] geomname [other]\n" msgstr " verb [-options] geomname [other]\n" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:339 msgid "Common verbs are:" msgstr "Общими командами являются:" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:341 msgid "" "label - to write metadata to devices so they can be recognized at tasting " "and brought up in geoms" msgstr "" "label - записать метаданные в устройства, чтобы они могли быть опознаны в " "процессе тестирования и использованы в соответствующих экземплярах geom" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:342 msgid "destroy - to destroy metadata, so the geoms get destroyed" msgstr "" "destroy - разрушить метаданные, за которым последует разрушение экземпляров " "geom" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:344 msgid "Common options are:" msgstr "Общие опции:" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:346 msgid "`-v` : be verbose" msgstr "`-v` : детальный вывод" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:347 msgid "`-f` : force" msgstr "`-f` : принудить" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:351 msgid "" "Many actions, such as labeling and destroying metadata can be performed in " "userland. For this, `struct g_command` provides field `gc_func` that can be " "set to a function (in the same [.filename]#.so#) that will be called to " "process a verb. If `gc_func` is NULL, the command will be passed to kernel " "module, to `.ctlreq` function of the geom class." msgstr "" "Некоторые операции, к примеру маркирование метаданными и разрушение " "метаданных могут быть выполнены из пространства пользовательских процессов. " "Для этого, структура `g_command` содержит поле `gc_func`, которое может быть " "установлено на функцию (в том-же [.filename]#.so#), которая будет вызвана " "для обработки команды. В случае, когда `gc_func` равно NULL, команда будет " "передана модулю ядра: функции `.ctlreq` класса GEOM." #. type: Title === #: documentation/content/en/articles/geom-class/_index.adoc:353 #, no-wrap msgid "Geoms" msgstr "Экземпляры geom" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:357 msgid "" "Geoms are instances of GEOM classes. They have internal data (a softc " "structure) and some functions with which they respond to external events." msgstr "" "У экземпляров классов GEOM есть внутренние данные, которые хранятся в " "структурах softc, а также есть некоторые функции, посредством которых они " "реагируют на внешние события." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:359 msgid "The event functions are:" msgstr "Функции событий:" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:361 msgid "`.access` : calculates permissions (read/write/exclusive)" msgstr "" "`.access` : просчитывает права доступа (чтение/запись/исключительный доступ)" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:362 msgid "`.dumpconf` : returns XML-formatted information about the geom" msgstr "`.dumpconf` : возвращает информацию о экземпляре geom; формат XML" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:363 msgid "`.orphan` : called when some underlying provider gets disconnected" msgstr "" "`.orphan` : вызывается, когда отсоединяется любой из низлежащих поставщиков " "geom" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:364 msgid "`.spoiled` : called when some underlying provider gets written to" msgstr "" "`.spoiled` : вызывается, когда производится запись в низлежащий поставщик " "geom" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:365 msgid "`.start` : handles I/O" msgstr "`.start` : обрабатывает ввод/вывод" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:367 msgid "" "These functions are called from the `g_down` kernel thread and there can be " "no sleeping in this context, (see definition of sleeping elsewhere) which " "limits what can be done quite a bit, but forces the handling to be fast." msgstr "" "Эти функции вызываются из ядерного потока `g_down` и в этом контексте не " "может быть блокировок (поищите определение \"блокировка\" в других " "источниках), что немного ограничивает свободу действий, но способствует " "быстроте обработки." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:369 msgid "" "Of these, the most important function for doing actual useful work is the " "`.start`() function, which is called when a BIO request arrives for a " "provider managed by a instance of geom class." msgstr "" "Из вышеупомянутых, наиболее важной и выполняющей полезную работу функцией " "является `.start`(), которая вызывается всякий раз, когда поставщику geom, " "управляемому экземпляром класса, приходит запрос BIO." #. type: Title === #: documentation/content/en/articles/geom-class/_index.adoc:371 #, no-wrap msgid "GEOM Threads" msgstr "Потоки выполнения системы geom" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:374 msgid "There are three kernel threads created and run by the GEOM framework:" msgstr "" "Системой GEOM в ядре ОС создаются и используются три потока выполнения " "(kernel threads):" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:376 msgid "" "`g_down` : Handles requests coming from high-level entities (such as a " "userland request) on the way to physical devices" msgstr "" "`g_down` : Обрабатывает запросы, приходящие от высокоуровневых сущностей " "(таких как запросы из пространства пользовательских процессов) на пути к " "физическим устройствам" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:377 msgid "" "`g_up` : Handles responses from device drivers to requests made by higher-" "level entities" msgstr "" "`g_up` : Обрабатывает ответы от драйверов устройств на запросы, выполненные " "высокоуровневыми сущностями" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:378 msgid "" "`g_event` : Handles all other cases: creation of geom instances, access " "counting, \"spoil\" events, etc." msgstr "" "`g_event` : Отрабатывает в остальных случаях, как-то создание экземпляра " "geom, просчитывание прав доступа, события \"повреждения\" и т.п." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:380 msgid "" "When a user process issues \"read data X at offset Y of a file\" request, " "this is what happens:" msgstr "" "Когда пользовательский процесс запрашивает \"прочитать данные X по смещению " "Y файла\", происходит следующее:" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:382 msgid "" "The filesystem converts the request into a struct bio instance and passes it " "to the GEOM subsystem. It knows what geom instance should handle it because " "filesystems are hosted directly on a geom instance." msgstr "" "Файловая система преобразует запрос в экземпляр структуры bio и передаёт его " "системе GEOM. Файловая система \"знает\", что экземпляр geom должен " "обработать запрос, так как файловые системы размещаются непосредственно над " "экземпляром geom." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:383 msgid "" "The request ends up as a call to the `.start`() function made on the g_down " "thread and reaches the top-level geom instance." msgstr "" "Запрос завершается вызовом функции `.start`() в потоке g_down и достигает " "верхнего экземпляра geom." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:384 msgid "" "This top-level geom instance (for example the partition slicer) determines " "that the request should be routed to a lower-level instance (for example the " "disk driver). It makes a copy of the bio request (bio requests _ALWAYS_ need " "to be copied between instances, with `g_clone_bio`()!), modifies the data " "offset and target provider fields and executes the copy with `g_io_request`()" msgstr "" "Верхний экземпляр geom (например, это секционировщик разделов (partition " "slicer)) определяет, что запрос должен быть переадресован нижестоящему " "экземпляру geom (к примеру, драйверу диска). Вышестоящий экземпляр geom " -"создает копию запроса bio (запросы bio _ВСЕГДА_ копируются при передаче " +"создаёт копию запроса bio (запросы bio _ВСЕГДА_ копируются при передаче " "между экземплярами geom при помощи `g_clone_bio`()!), изменяет поля смещения " "и целевого поставщика geom и запускает на обработку копию при помощи функции " "`g_io_request`()" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:385 msgid "" "The disk driver gets the bio request also as a call to `.start`() on the " "`g_down` thread. It talks to hardware, gets the data back, and calls " "`g_io_deliver`() on the bio." msgstr "" "Драйвер диска также получает запрос bio, как вызов функции `.start`() в " "потоке `g_down`. Драйвер обращается к контроллеру диска, получает блок " "данных и вызывает функцию `g_io_deliver`() используя копию запроса bio." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:386 msgid "" "Now, the notification of bio completion \"bubbles up\" in the `g_up` thread. " "First the partition slicer gets `.done`() called in the `g_up` thread, it " "uses information stored in the bio to free the cloned `bio` structure (with " "`g_destroy_bio`()) and calls `g_io_deliver`() on the original request." msgstr "" "Теперь, извещение о завершении bio \"всплывает\" в потоке `g_up`. Сначала в " "потоке `g_up` вызывается функция `.done`() секционировщика разделов, " "последний использует полученную информацию, разрушает клонированный " "экземпляр структуры bio посредством `g_destroy_bio`() и вызывает " "`g_io_deliver`() используя первоначальный запрос." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:387 msgid "The filesystem gets the data and transfers it to userland." msgstr "" "Файловая система получает данные и передаёт их пользовательскому процессу." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:389 msgid "" "See man:g_bio[9] man page for information how the data is passed back and " "forth in the `bio` structure (note in particular the `bio_parent` and " "`bio_children` fields and how they are handled)." msgstr "" "За информацией о том, как данные передаются в структуре `bio` между " "экземплярами geom, смотрите man:g_bio[9] (обратите внимание на использование " "полей `bio_parent` и `bio_children`)." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:392 msgid "" "One important feature is: __THERE CAN BE NO SLEEPING IN G_UP AND G_DOWN " "THREADS__. This means that none of the following things can be done in " "those threads (the list is of course not complete, but only informative):" msgstr "" "Важный момент в том, что __НЕЛЬЗЯ ДОПУСКАТЬ БЛОКИРОВОК В ПОТОКАХ G_UP И " "G_DOWN__. Вот неполный перечень того, что нельзя делать в этих потоках:" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:394 msgid "Calls to `msleep`() and `tsleep`(), obviously." msgstr "Вызывать функции `msleep`() или `tsleep`()." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:395 msgid "" "Calls to `g_write_data`() and `g_read_data`(), because these sleep between " "passing the data to consumers and returning." msgstr "" "Использовать функции `g_write_data`() и `g_read_data`(), так как они " "блокируются в момент обмена данными с потребителями geom." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:396 msgid "Waiting for I/O." msgstr "Ожидать ввод/вывод." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:397 msgid "Calls to man:malloc[9] and `uma_zalloc`() with `M_WAITOK` flag set" msgstr "" "Вызывать man:malloc[9] и `uma_zalloc`() с установленным флагом `M_WAITOK`" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:398 msgid "sx and other sleepable locks" msgstr "Использовать man:sx[9]" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:402 msgid "" "This restriction is here to stop GEOM code clogging the I/O request path, " "since sleeping is usually not time-bound and there can be no guarantees on " "how long will it take (there are some other, more technical reasons also). " "It also means that there is not much that can be done in those threads; for " "example, almost any complex thing requires memory allocation. Fortunately, " "there is a way out: creating additional kernel threads." msgstr "" "Это ограничение на код GEOM призвано избежать от \"засорения\" пути запроса " "ввода/вывода, так как блокировки обычно не имеют четких временных границ, и " "нет гарантий на занимаемое время (также на то есть и другие технические " "причины). Это также значит, что в вышеупомянутых потоках сколь-нибудь " "сложные операции выполнить нельзя, например: любое сложное преобразование " "требует выделения памяти. К счастью решение есть: создание дополнительных " "ядерных потоков." #. type: Title === #: documentation/content/en/articles/geom-class/_index.adoc:404 #, no-wrap msgid "Kernel Threads for Use in GEOM Code" msgstr "Ядерные потоки выполнения, предназначенные для использования в коде geom" #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:407 msgid "" "Kernel threads are created with man:kthread_create[9] function, and they are " "sort of similar to userland threads in behavior, only they cannot return to " "caller to signify termination, but must call man:kthread_exit[9]." msgstr "" "Ядерные потоки выполнения создаются функцией man:kthread_create[9], в своём " "поведении они схожи с потоками, созданными в пространстве пользовательских " "процессов, но есть одно отличие: они не могут известить вызвавший их поток о " "своём завершении; по завершению - необходимо вызывать man:kthread_exit[9]." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:410 msgid "" "In GEOM code, the usual use of threads is to offload processing of requests " "from `g_down` thread (the `.start`() function). These threads look like " "\"event handlers\": they have a linked list of event associated with them " "(on which events can be posted by various functions in various threads so it " "must be protected by a mutex), take the events from the list one by one and " "process them in a big `switch`() statement." msgstr "" "В коде GEOM обычное назначение этих потоков - разгрузить поток `g_down` " "(функцию `.start`() ) от обработки запросов. Эти потоки подобны " "\"обработчикам событий\" (\"event handlers\"): у них есть очередь событий " "(которая наполняется событиями от разных функций из разных потоков; очередь " "необходимо защищать мьютексом), события из очереди выбираются одно за другим " "и обрабатываются в большом блоке `switch`()." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:415 msgid "" "The main benefit of using a thread to handle I/O requests is that it can " "sleep when needed. Now, this sounds good, but should be carefully thought " "out. Sleeping is well and very convenient but can very effectively destroy " "performance of the geom transformation. Extremely performance-sensitive " "classes probably should do all the work in `.start`() function call, taking " "great care to handle out-of-memory and similar errors." msgstr "" "Основное преимущество использования отдельного потока, который обрабатывает " "запросы ввода/вывода, то, что он может блокироваться по мере необходимости. " "Это, несомненно, привлекательно, но должно быть хорошо обдумано. " "Блокирование - хорошо и удобно, но может существенно снизить " "производительность преобразований данных в системе GEOM. Особо " "требовательные к производительности классы могут делать всю работу в функции " "`.start`(), уделяя особое внимание ошибкам при работе с памятью." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:419 msgid "" "The other benefit of having a event-handler thread like that is to serialize " "all the requests and responses coming from different geom threads into one " "thread. This is also very convenient but can be slow. In most cases, " "handling of `.done`() requests can be left to the `g_up` thread." msgstr "" "Еще одно преимущество потока \"обработчика событий\" это сериализация всех " "запросов и ответов, приходящих с разных потоков geom в один поток. Это также " "удобно, но может быть медленным. В большинстве случаев, обработка запросов " "функцией `.done`() может быть оставлена потоку `g_up`." #. type: Plain text #: documentation/content/en/articles/geom-class/_index.adoc:422 msgid "" "Mutexes in FreeBSD kernel (see man:mutex[9]) have one distinction from their " "more common userland cousins - the code cannot sleep while holding a " "mutex). If the code needs to sleep a lot, man:sx[9] locks may be more " "appropriate. On the other hand, if you do almost everything in a single " "thread, you may get away with no mutexes at all." msgstr "" "У мьютексов в ядре FreeBSD (man:mutex[9]) есть одно различие с их аналогами " "из пространства пользовательских процессов - во время удержания мьютекса в " "коде не должно быть блокировки. Если в коде необходимо блокирование, то " "лучше использовать man:sx[9]. С другой стороны, если вся ваша работа " "выполняется в одном потоке, вы можете обойтись вообще без мьютексов." #, no-wrap #~ msgid "" #~ "dumpdev=\"/dev/ad0s4b\"\n" #~ "dumpdir=\"/usr/core\n" #~ msgstr "" #~ "dumpdev=\"/dev/ad0s4b\"\n" #~ "dumpdir=\"/usr/core\"\n" diff --git a/documentation/content/ru/articles/gjournal-desktop/_index.adoc b/documentation/content/ru/articles/gjournal-desktop/_index.adoc index cd44ca5544..d242a8e260 100644 --- a/documentation/content/ru/articles/gjournal-desktop/_index.adoc +++ b/documentation/content/ru/articles/gjournal-desktop/_index.adoc @@ -1,882 +1,882 @@ --- authors: - author: 'Manolis Kiagias' email: manolis@FreeBSD.org - author: 'Vladlen Popolitov' email: vladlen@FreeBSD.org description: 'Настройка журналирования UFS для настольного компьютера' tags: ["UFS", "Journaling" , "Desktop", "FreeBSD"] title: 'Настройка журналирования UFS для настольного компьютера' trademarks: ["freebsd", "general"] --- = Настройка журналирования UFS для настольного компьютера :doctype: article :toc: macro :toclevels: 2 :icons: font :sectnums: :sectnumlevels: 6 :source-highlighter: rouge :experimental: :images-path: articles/gjournal-desktop/ ifdef::env-beastie[] ifdef::backend-html5[] include::shared/authors.adoc[] include::shared/mirrors.adoc[] include::shared/releases.adoc[] include::shared/attributes/attributes-{{% lang %}}.adoc[] include::shared/{{% lang %}}/teams.adoc[] include::shared/{{% lang %}}/mailing-lists.adoc[] include::shared/{{% lang %}}/urls.adoc[] :imagesdir: ../../../images/{images-path} endif::[] ifdef::backend-pdf,backend-epub3[] include::../../../../shared/asciidoctor.adoc[] endif::[] endif::[] ifndef::env-beastie[] include::../../../../../shared/asciidoctor.adoc[] endif::[] [.abstract-title] Аннотация Журналируемая файловая система использует журнал для записи обновлений файловой системы и обеспечивает целостность данных в случае сбоя системы или отключения питания. Несмотря на то, что несохранённые изменения в файлах всё ещё могут быть утеряны, журналирование значительно снижает риск повреждения файловой системы из-за некорректного завершения работы и существенно сокращает время восстановления. Хотя файловая система UFS, используемая в FreeBSD, не реализует журналирование как встроенную функцию на уровне диска, FreeBSD предоставляет поддержку журналирования через механизмы на уровне файловой системы (Soft Updates с журналированием), а также через фреймворк GEOM (`gjournal`). В этой статье описываются доступные механизмы журналирования UFS и объясняется их целесообразное использование в современных системах FreeBSD. _Содержание было проверено и обновлено для версий FreeBSD с 13 по 15_. ''' toc::[] [[introduction]] == Введение Серверное оборудование обычно хорошо защищено от потери питания. Настольный компьютер часто подвержен неожиданным пропаданиям питания, случайным нажатиям кнопки Reset и другим происшествиям (часто связанным с неосторожностью пользователей), которые могут привести к непредвиденным выключениям и оставить файловую систему в несогласованном состоянии. Традиционно это требовало запуска `fsdk`, что на больших файловых системах требует значительного времени. В очень редких случаях повреждения файловой системы достигают того уровня, при котором становится необходимым вмешательство пользователя и данные могут быть утерянными. FreeBSD предоставляет два различных механизма журналирования для файловой системы UFS: * Журналирование с Soft Updates * Журналирование с командой GEOM `gjournal` Эти механизмы функционируют на различных уровнях системы и обладают разными характеристиками производительности и семантики. [IMPORTANT] ==== Для большинства современных систем FreeBSD, включая настольные компьютеры и серверы общего назначения, рекомендуется использовать *Soft Updates с журналированием*. GEOM журналирование — это устаревший и специализированный механизм, и его следует использовать только тогда, когда требуются его специфические семантики. ==== В этой статье объясняются оба механизма, их различия и правильное современное использование. Прочтите эту главу, чтобы узнать: * Доступные механизмы журналирования для файловой системы UFS в FreeBSD и их различия. * Когда использовать журналирование на уровне файловой системы с Soft Updates и когда может быть уместно журналирование GEOM. * Как включить или отключить журналирование Soft Updates на существующих файловых системах UFS. * Как настроить журналирование GEOM на новых или существующих разделах, включая необходимую поддержку ядра и вопросы определения размера журнала. * Какие изменения конфигурации необходимы для монтирования журналируемых файловых систем и как журналирование влияет на поведение системы. * Как диагностировать неполадки и разрешать проблемы, связанные с журналированием файловой системы UFS. Перед прочтением этой статьи вам необходимо: * Понимать базовые концепции таких операционных систем, как UNIX(R) и FreeBSD. * Быть знакомым с процедурой установки FreeBSD, используя bsdinstall. * Иметь базовые знания о разбиении дисков и файловых системах, включая такие инструменты, как gpart(8), newfs(8) и mount(8). [WARNING] ==== Некоторые процедуры, описанные в данной статье, включают изменение конфигурации файловой системы или диска и могут потребовать размонтирования файловых систем или изменения метаданных на диске. Перед внесением подобных изменений в работающей системе убедитесь, что доступны надежные _резервные копии_ всех важных данных. Включение журналирования Soft Updates на уровне файловой системы обычно безопасно и не требует переразбивки диска. Однако настройка журналирования GEOM включает низкоуровневые операции с диском и должна выполняться только опытными администраторами, полностью понимающими последствия. ==== [[understanding-journaling]] == Реализация журналирования в FreeBSD === Soft Updates с журналированием (рекомендуется) Soft Updates — это механизм обеспечения согласованности UFS по умолчанию в FreeBSD. В сочетании с журналированием он обеспечивает *журналирование метаданных* в самой файловой системе. Преимущества Soft Updates с журналированием включают: * Очень быстрое восстановление после сбоя (обычно за секунды) * Обычная семантика `sync(2)` и `fsync(2)` * Никаких дополнительных разделов или слоев GEOM * Простая настройка и обслуживание Из `tunefs(8)`: ____ Включение журналирования сокращает время, затрачиваемое fsck_ffs(8) на очистку файловой системы после сбоя, с нескольких минут или часов до нескольких секунд. ____ Этот механизм подходит практически для всех систем на основе UFS и является рекомендуемым по умолчанию. === Журналирование с командой GEOM `gjournal` GEOM журналирование работает на блочном уровне, ниже файловой системы. Оно журналирует все записи блоков, включая *как метаданные, так и данные файлов*. Ключевые характеристики журналирования GEOM: * Реализовано как класс GEOM (`geom_journal`) * Журналирует весь блочный ввод-вывод, а не только метаданные * Требует явного согласования от UFS с использованием флага `-J` * Отключает Soft Updates * Изменяет семантику `sync(2)` и `fsync(2)` [WARNING] ==== На файловых системах с журналированием GEOM, `sync(2)` и `fsync(2)` не гарантируют, что данные были записаны на постоянное хранилище. Для обеспечения сохранности необходимо использовать `gjournal sync`. ==== Из-за этих различий журналирование GEOM не рекомендуется для общего использования на настольных компьютерах или серверах. == Выбор подходящего метода журналирования В следующей таблице приведены рекомендуемые варианты использования: [cols="1,1", options="header"] |=== | Вариант использования | Рекомендуемый механизм | Настольная или портативная система | Журналирование с Soft Updates | Универсальный сервер | Журналирование с Soft Updates | Устаревшие системы UFS | Журналирование с Soft Updates | Требования к журналированию, не зависящие от файловой системы | Журналирование GEOM | Специализированное журналирование на уровне блоков | Журналирование GEOM |=== == Использование Soft Updates с журналированием Soft Updates с журналированием обеспечивают журналирование на уровне файловой системы для UFS. Этот механизм сохраняет целостность файловой системы, одновременно сохраняя оптимизации выделения и упорядочивания, характерные для Soft Updates. В отличие от журналирования GEOM, отдельное журналирующее устройство или раздел не требуется. === Обзор Soft Updates с журналированием записывают изменения метаданных файловой системы в журнал, хранящийся внутри самой файловой системы, реализованный как скрытый файл с именем [.filename]#.sujournal# в корне файловой системы. В случае сбоя или отключения питания ожидающие операции с метаданными воспроизводятся из журнала, что позволяет быстро смонтировать файловую систему без полной проверки согласованности. Эта форма журналирования применяется только к метаданным файловой системы. Целостность данных файлов остается ответственностью приложений. === Включение журналирования на существующей файловой системе Файловая система должна быть размонтирована или смонтирована в режиме только для чтения перед изменением настроек журналирования. [source, shell] ---- # umount /usr # tunefs -n enable -j enable /dev/ada0p2 # mount /usr ---- Дополнительная настройка не требуется. Можно использовать стандартные параметры монтирования. === Хранение журналов и их размер Размер журнала по умолчанию выбирается автоматически при включении ведения журнала. В большинстве случаев размер по умолчанию достаточен и не требует корректировки. При необходимости размер журнала в байтах может быть явно указан с помощью опции `-S` для `tunefs(8)`: [source, shell] ---- # tunefs -S 64000000 /dev/ada0p2 ---- Настройка размера журнала редко требуется и должна рассматриваться только для файловых систем с необычно высокой частотой обновления метаданных. === Проверка Soft Updates с журналированием Статус журналирования файловой системы UFS с использованием Soft Updates можно проверить с помощью `tunefs(8)` или `dumpfs(8)`. Чтобы отобразить текущие настройки файловой системы, выполните: [source, shell] ---- # tunefs -p /dev/ada0p2 | grep -i journal tunefs: soft updates journaling: (-j) enabled tunefs: gjournal: (-J) disabled ---- Ищите следующие индикаторы в выводе: * Soft Updates включены * Soft Updates с журналированием включены Или для проверки суперблока файловой системы можно использовать `dumpfs(8)`: [source, shell] ---- English type: delimited block - 4 # dumpfs /dev/ada0p2 | grep -i journal flags soft-updates+journal ---- Эти команды предназначены только для чтения и не изменяют состояние файловой системы. === Проверка и обслуживание файловой системы Хотя журналирование значительно сокращает время восстановления после сбоя, оно не устраняет необходимость периодических полных проверок файловой системы. * Журналирование гарантирует целостность, а не корректность * Ошибки носителя не исправляются журналированием * Периодическая проверка `fsck` все еще должна быть запланирована * Фоновый `fsck` может использоваться на работающих файловых системах == Использование журналирования GEOM (Продвинутый уровень) [WARNING] ==== Данный раздел предназначен для опытных пользователей, которые понимают последствия журналирования на уровне блоков и изменения семантики синхронизации. ==== === Обзор Возможность журналирования обеспечивается загрузкой модуля [.filename]#geom_journal.ko# в ядро (или сборкой собственного ядра с активированием соответствующих опций) и использованием команды `gjournal` для конфигурирования файловой системы. В общем, вы предпочтете журналировать файловые системы большого размера, к примеру - [.filename]#/usr#. Однако, вам придется зарезервировать некоторое количество свободного места (см. следующий раздел). Журналирование GEOM реализовано модулем ядра `geom_journal` и настраивается с помощью утилиты `gjournal(8)`. Оно обеспечивает журналирование на уровне блоков ниже слоя файловой системы и требует явной поддержки со стороны UFS. При использовании журналирования GEOM требуется некоторое дисковое пространство для хранения самого журнала. Провайдер, содержащий данные файловой системы, называется _провайдером данных_, а провайдер, хранящий журнал, называется _провайдером журнала_. При журналировании существующей (непустой) файловой системы провайдеры данных и журнала должны быть раздельными. При журналировании новой, пустой файловой системы, один провайдер может использоваться для хранения как данных, так и информации журнала. В обоих случаях `gjournal(8)` объединяет провайдеры данных и журнала для создания нового журналируемого провайдера, который затем монтируется файловой системой. Например: * Файловая система `/usr` расположена на `/dev/ada0p2` и уже содержит данные. * Свободное дисковое пространство выделено в отдельном разделе, `/dev/ada0p4`, для хранения журнала. -* После настройки журналирования GEOM создается новый провайдер `/dev/ada0p2.journal`. Этот журналируемый провайдер объединяет `/dev/ada0p2` в качестве провайдера данных и `/dev/ada0p4` в качестве провайдера журнала и используется для всех последующих операций файловой системы. +* После настройки журналирования GEOM создаётся новый провайдер `/dev/ada0p2.journal`. Этот журналируемый провайдер объединяет `/dev/ada0p2` в качестве провайдера данных и `/dev/ada0p4` в качестве провайдера журнала и используется для всех последующих операций файловой системы. Объем дискового пространства, необходимого для журнала, в первую очередь зависит от интенсивности записи в файловую систему, а не от размера поставщика данных. Системам с постоянной или импульсной активностью записи требуются журналы большего размера, чтобы избежать чрезмерного переключения журналов или ограничения записи. Из справочной страницы `gjournal(8)`: * Размер журнала по умолчанию составляет 1 ГБ. * Рекомендуемый минимальный размер журнала составляет удвоенный объем установленной оперативной памяти. * Размер журнала должен выбираться на основе ожидаемой нагрузки записи, а не размера файловой системы. Недостаточный размер журнала может привести к снижению производительности или вынужденным переключениям журнала при высокой нагрузке на запись. Для получения дополнительной информации о журналировании, пожалуйста, прочитайте страницу справочника, посвященную man:gjournal[8]. [[reserve-space]] === Действия, необходимые во время установки FreeBSD В этом разделе описывается необязательная подготовка во время установки для систем, настроенных на использование журналирования GEOM. Цель — зарезервировать дисковое пространство для журнальных провайдеров, которые впоследствии будут связаны с файловыми системами `/usr` и `/var`. ==== Выделение места под журналирование На типичной системе с одним диском операционная система, установленное программное обеспечение и пользовательские данные находятся на одном устройстве. Стандартное автоматическое разбиение, выполняемое установщиком FreeBSD, выделяет большую часть доступного пространства под `/usr`, с меньшими разделами для `/var` и других точек монтирования. По умолчанию установщик выделяет всё доступное дисковое пространство для файловых систем и не оставляет неиспользуемого места. Если планируется использование журналирования GEOM для существующих (непустых) файловых систем, необходимо зарезервировать дополнительное дисковое пространство для размещения журнальных провайдеров. Каждая файловая система, которая будет журналироваться, требует собственного журнального провайдера. Поскольку `/usr` обычно занимает наибольшую часть диска, это наиболее практичный раздел для небольшого уменьшения, чтобы освободить место для журналируемых провайдеров. В нашем примере журналирование GEOM планируется как для `/usr`, так и для `/var`. ==== Стратегия разбиения на разделы Во время установки используйте режим ручного разбиения, предоставляемый установщиком. Создайте любую поддерживаемую файловую систему для `/`, а также стандартные разделы UFS для `/usr` и `/var`, но уменьшите размер `/usr`, чтобы оставить достаточно нераспределенного пространства в конце диска. Из оставшегося нераспределенного пространства создайте два дополнительных раздела, которые будут использоваться исключительно в качестве журнальных провайдеров: * Один раздел для журнала `/usr` * Один раздел для журнала `/var` Эти разделы не должны иметь назначенных точек монтирования и не должны использоваться для подкачки. Они останутся неиспользованными до тех пор, пока не будут явно связаны с соответствующими поставщиками данных с помощью `gjournal(8)` после установки. Типичная схема может выглядеть следующим образом: .Разделы, Зарезервированные для Журналирования GEOM [cols="1,1,2", options="header"] |=== | Поставщик | Предназначение | Заметки |/dev/ada0p2 |/var |Файловая система UFS (поставщик данных) |/dev/ada0p3 |/usr |Файловая система UFS (поставщик данных) |/dev/ada0p4 |Журнал для /var |Неформатированный, неиспользуемый раздел |/dev/ada0p5 |Журнал для /usr |Неформатированный, неиспользуемый раздел |=== Точные названия устройств могут различаться в зависимости от структуры диска и схемы разделов. Настоятельно рекомендуется записать имена провайдеров во время установки, так как они потребуются при настройке журнала. ==== Соображения по размеру журнала Размер журнала зависит от ожидаемой нагрузки на запись, а не от размера файловой системы. Для систем общего назначения обычно достаточно журналов размером 1–2 ГБ. Системам с постоянной или импульсной активностью записи могут потребоваться журналы большего размера. Выделяйте пространство под журнал экономно во время установки, так как изменение размера разделов позже может потребовать дополнительного времени простоя. ==== Завершение инсталляции После резервирования необходимых разделов завершите установку FreeBSD в обычном режиме. Рекомендуется отложить установку стороннего программного обеспечения и дополнительную настройку системы до полной настройки журналирования GEOM. На этом этапе система загрузится с использованием стандартных файловых систем UFS. Зарезервированные журнальные разделы останутся неиспользованными до тех пор, пока журналирование не будет явно включено. [[first-boot]] ==== Первая загрузка после установки После первого успешного запуска немедленные изменения конфигурации не требуются. Следует убедиться, что система загружается и работает нормально, прежде чем продолжить. После того, как подтверждено, что базовая система работоспособна, следующие шаги включают: * Загрузка или включение поддержки журналирования GEOM * Связывание журнальных провайдеров с соответствующими провайдерами данных * Обновление `/etc/fstab` для монтирования журналируемых устройств Эти шаги описаны в следующем разделе. [[configure-journal]] === Настройка журналирования [[running-gjournal]] ==== Включение журналирования GEOM в существующих файловых системах В этом разделе описывается, как включить журналирование GEOM для файловых систем `/usr` и `/var`, используя разделы, подготовленные в процессе установки. После резервирования необходимых журнальных провайдеров можно настроить журналирование GEOM. Поскольку файловые системы, подлежащие журналированию, не должны быть смонтированы, систему необходимо переключить в однопользовательский режим. Залогиньтесь `root` и введите: [source, shell] .... # shutdown now .... Нажмите kbd:[Enter] для получения приглашения командного интерпретатора в режиме root. Нам необходимо будет размонтировать разделы, которые подлежат журналированию, в нашем примере это [.filename]#/usr# и [.filename]#/var#: [source, shell] .... # umount /usr /var .... Загрузите модуль ядра GEOM journaling: [source, shell] .... # gjournal load .... Далее, свяжите каждого поставщика данных с соответствующим поставщиком журналов. Используйте свои заметки, чтобы определить, какой раздел будет использоваться для каждого журнала. В этом примере: * `/usr` находится на `/dev/ada0p3`, а его журнальный провайдер — `/dev/ada0p5` * `/var` находится на `/dev/ada0p2`, а его журнальный провайдер — `/dev/ada0p4` Создайте журналируемые провайдеры с помощью `gjournal(8)`: [source, shell] .... # gjournal label ada0p3 ada0p5 GEOM_JOURNAL: Journal 2948326772: ada0p5 contains journal. GEOM_JOURNAL: Journal 2948326772: ada0p3 contains data. GEOM_JOURNAL: Journal ada0p3 clean. # gjournal label ada0p2 ada0p4 GEOM_JOURNAL: Journal 3193218002: ada0p4 contains journal. GEOM_JOURNAL: Journal 3193218002: ada0p2 contains data. GEOM_JOURNAL: Journal ada0p2 clean. .... [NOTE] ==== Если `gjournal` сообщает, что последний сектор провайдера используется, команда завершится неудачей. На свежесозданных или неиспользуемых разделах безопасно повторить операцию с флагом `-f` для принудительной инициализации: [source, shell] .... # gjournal label -f /dev/ada0p2 /dev/ada0p4 .... ==== После маркировки создаются два новых журналируемых провайдера: * `/dev/ada0p3.journal` для `/usr` * `/dev/ada0p2.journal` для `/var` Эти устройства заменят исходные источники данных при монтировании файловых систем. Перед монтированием необходимо установить для них флаг журнала и снять флаг Soft Updates: [source, shell] .... # tunefs -J enable -n disable -j disable /dev/ada0p3.journal tunefs: soft updates journaling cleared but soft updates still set tunefs: remove .sujournal to reclaim space tunefs: gjournal set tunefs: soft updates cleared # tunefs -J enable -n disable -j disable /dev/ada0p2.journal tunefs: soft updates journaling cleared but soft updates still set tunefs: remove .sujournal to reclaim space tunefs: gjournal set tunefs: soft updates cleared .... Теперь, смонтируйте новые устройства в соответствующие места файловой системы (обратите внимание на то, что мы можем использовать опцию монтирования `async`) и удалите [.filename]#.sujournal#, чтобы освободить место на диске: [source, shell] .... # mount -o async /dev/ada0p2.journal /var # rm /var/.sujournal # mount -o async /dev/ada0p3.journal /usr # rm /usr/.sujournal .... Откройте [.filename]#/etc/fstab# и исправьте записи для следующих файловых систем: [.filename]#/usr# и [.filename]#/var#: [.programlisting] .... /dev/ada0p3.journal /usr ufs rw,async 2 2 /dev/ada0p2.journal /var ufs rw,async 2 2 .... [WARNING] ==== Проверьте корректность всех указанных параметров - в противном случае после перезагрузки возможны проблемы со стандартным запуском системы! ==== Наконец, внесите изменения в [.filename]#/boot/loader.conf#, добавив строку для автоматической загрузки модуля man:gjournal[8] при каждом старте системы: [.programlisting] .... geom_journal_load="YES" .... Поздравляем! Ваша система теперь настроена для журналирования. Вы можете ввести команду `exit` для возврата в многопользовательский режим или перезагрузить систему для проверки конфигурации (рекомендуется). [source, shell] .... # shutdown -r now .... Во время перезагрузки вы увидите сообщение следующего вида: [source, shell] .... # dmesg | grep GEOM_JOURNAL GEOM_JOURNAL: Journal 2948326772: ada0p4 contains journal. GEOM_JOURNAL: Journal 3193218002: ada0p5 contains journal. GEOM_JOURNAL: Journal 2948326772: ada0p2 contains data. GEOM_JOURNAL: Journal ada0p2 clean. GEOM_JOURNAL: Journal 3193218002: ada0p3 contains data. GEOM_JOURNAL: Journal ada0p3 clean. .... После некорректного завершения работы сообщения будут немного отличаться, например: [source, shell] .... GEOM_JOURNAL: Journal ada0p2 consistent. .... Обычно это означает, что man:gjournal[8] использовал информацию из журнала для приведения файловой системы в согласованное состояние. [[gjournal-new]] ==== Включение журналирования GEOM на вновь созданных разделах Процедура, описанная ранее, необходима при включении журналирования GEOM на файловых системах, которые уже содержат данные. При журналировании только что созданного, пустого раздела процесс проще, так как и данные, и журнальные провайдеры могут находиться в одном разделе. Такой подход обычно используется для новых дисков или недавно выделенных разделов, которые еще не были отформатированы под файловую систему. Процедура, описанная выше, необходима для подключения журналирования разделов, содержащих данные. Журналирование пустых разделов немного проще, ввиду того, что поставщик данных и поставщик журнала могут быть размещены на одном и том же разделе. Например, предположим, что был установлен новый жёсткий диск и был создан новый раздел [.filename]#/dev/ada1p1#. Создание журнала не сложнее набора: [source, shell] .... # gjournal label /dev/ada1p1 .... Размер журнала - 1 Гб по умолчанию. Однако, вы можете изменить это значение используя ключ `-s`. Значение можно задавать в байтах, в килобайтах, мегабайтах или гигабайтах (используя суффикс `K`, `M` или `G`). Имейте ввиду, что команда `gjournal` не позволит вам создать журнал недопустимо малого размера. К примеру, чтобы создать журнал размером в 2Гб, можно использовать следующую команду: [source, shell] .... # gjournal label -s 2G /dev/ada1p1 .... Далее, вы можете создать файловую систему UFS на новом разделе, разрешить журналирование, используя `newfs(8)` на устройстве `.journal`, и запретить Soft Updates, используя `tunefs(8)`: [source, shell] .... # newfs -J /dev/ada1p1.journal # tunefs -n disable -j disable /dev/ada1p1.journal .... После создания файловой системы её можно смонтировать обычным способом. Например, чтобы смонтировать её в `/data`: [source, shell] .... # mount /dev/ada1p1.journal /data .... Чтобы обеспечить автоматическое монтирование файловой системы при загрузке, добавьте запись в [.filename]#/etc/fstab#: [.programlisting] .... /dev/ada1p1.journal /data ufs rw,async 2 2 .... ===== Заметки по использованию При использовании одного провайдера для хранения данных и журналов: * Раздел должен быть пустым перед выполнением `gjournal label` * Журнальное пространство выделяется внутри раздела диска * Размер файловой системы будет уменьшен на размер журнала [[configure-kernel]] === Встраивание журналирования в собственное ядро Если вы не желаете загружать `geom_journal` как модуль, то можно встроить его функции прямо в ваше специализированное ядро. Редактируя конфигурационный файл ядра, убедитесь, что в нём находятся следующие две строки: [.programlisting] .... options UFS_GJOURNAL <1> options GEOM_JOURNAL <2> .... <.> Обратите внимание — это уже есть в GENERIC <.> Вам надо добавить эту опцию Соберите и установите новое ядро следуя указаниям extref:{handbook}kernelconfig[Руководства FreeBSD., kernelconfig] И не забудьте удалить соответствующую строку загрузки модуля ("load") из [.filename]#/boot/loader.conf# (если на предыдущем этапе она была туда внесена). === Проверка GEOM журналирования Статус журналирования GEOM можно уточнить, проверив активные провайдеры GEOM. Чтобы вывести список всех активных устройств журналирования GEOM, выполните: [source, shell] ---- # gjournal list ---- Или для просмотра сводки состояния журнала: [source, shell] ---- # gjournal status ---- Журналируемые файловые системы обозначаются именами устройств, оканчивающимися на `.journal`. Наличие этих провайдеров указывает на активность журналирования GEOM. Дополнительную информацию о цепочке устройств GEOM можно получить с помощью: [source, shell] ---- # geom -t ---- Или для проверки суперблока файловой системы можно использовать `dumpfs(8)`: [source, shell] ---- # dumpfs /dev/ada0p2.journal | grep -i journal flags gjournal ---- [[troubleshooting-journaling]] [[troubleshooting-gjournal]] == Устранение неполадок с журналированием Этот раздел содержит часто задаваемые вопросы касательно неполадок, связанных с журналированием. === Я получаю паники ядра во время высокой дисковой активности. Это связано с журналированием GEOM? На современных системах FreeBSD аварийные остановки системы, вызванные исключительно недостаточным размером журнала GEOM, встречаются редко. При продолжительных или интенсивных всплесках нагрузки на запись, недостаточный размер журнала обычно приводит к регулированию записи или временным задержкам ввода-вывода во время сброса журнала на устройство хранения данных. Аварийная остановка системы может возникнуть лишь в исключительных случаях, обычно в сочетании с дополнительными проблемами, такими как ошибки ввода-вывода или исчерпание ресурсов, когда продолжение работы может угрожать целостности файловой системы. Если наблюдаются аварийные остановки при интенсивной активности записи, рекомендуется увеличить размер журнала для затронутой файловой системы. === Я допустил некоторые ошибки во время конфигурирования, теперь система не загружается. Можно это как-нибудь исправить? Вы либо забыли внести запись (опечатались) в [.filename]#/boot/loader.conf#, либо есть ошибки в файле [.filename]#/etc/fstab#. Это легко исправить. Во время загрузки системы, когда процесс загрузки остановится и появится запрос входа в однопользовательский режим (например, после сбоя монтирования или ошибки `fsck`), нажмите kbd:[Enter], чтобы получить приглашение командного интерпретатора в однопользовательском режиме. Потом, проверьте возможные варианты: [source, shell] .... # cat /boot/loader.conf .... Убедитесь, что следующая строка существует и написана правильно: [.programlisting] .... geom_journal_load="YES" .... Если отсутствует запись `geom_journal_load`, или она содержит ошибки, журналируемые устройства не создадутся. Загрузите модуль вручную, примонтируйте все разделы и переходите в многопользовательский режим (продолжайте загрузку): [source, shell] .... # gjournal load GEOM_JOURNAL: Journal 2948326772: ada0p4 contains journal. GEOM_JOURNAL: Journal 3193218002: ada0p5 contains journal. GEOM_JOURNAL: Journal 2948326772: ada0p2 contains data. GEOM_JOURNAL: Journal ada0p2 clean. GEOM_JOURNAL: Journal 3193218002: ada0p3 contains data. GEOM_JOURNAL: Journal ada0p3 clean. # mount -a # exit (boot continues) .... Если же запись о `geom_journal_load` верна, то проверьте [.filename]#/etc/fstab#. Вероятней всего, что вы обнаружите опечатку или отсутствие необходимой записи. В этом случае смонтируйте вручную оставшиеся разделы и продолжите загрузку в многопользовательский режим. === Возможно ли отказаться от журналирования и вернуться к моей привычной файловой системе с механизмом Soft Updates? Несомненно. Используйте приведённую ниже последовательность действий, которая обращает изменения. Разделы, созданные для поставщиков журналов, могут позже быть использованы для других целей. Залогиньтесь `root` и переведите систему в однопользовательский режим: [source, shell] .... # shutdown now .... Размонтируйте журналируемые разделы: [source, shell] .... # umount /usr /var .... Синхронизируйте журналы: [source, shell] .... # gjournal sync .... Остановите поставщиков журналов: [source, shell] .... # gjournal stop ada0p2.journal # gjournal stop ada0p3.journal .... Следующий шаг должен быть выполнен с выгруженным модулем ядра gjournal. Если следующая команда завершится неудачей: [source, shell] ... # gjournal unload ... Убедитесь, что следующая строка присутствует в [.filename]#/boot/loader.conf# и написана правильно: [.programlisting] .... geom_journal_load="NO" .... Перезагрузите ваш компьютер без модуля ядра gjournal: [source, shell] .... # shutdown -r now .... Войдите в систему в однопользовательском режиме еще раз. Удалите метаданные журналирования со всех задействованных устройств: [source, shell] .... # gjournal clear ada0p2 # gjournal clear ada0p3 # gjournal clear ada0p4 # gjournal clear ada0p5 .... Снимите флаг журналирования и установите флаги механизма Soft Updates: [source, shell] .... # tunefs -J disable -n enable -j enable ada0p2 tunefs: soft updates journaling set tunefs: gjournal cleared tunefs: soft updates set # tunefs -J disable -n enable -j enable ada0p3 tunefs: soft updates journaling set tunefs: gjournal cleared tunefs: soft updates set .... Смонтируйте вручную старые (первоначальные) устройства: [source, shell] .... # mount -o rw /dev/ada0p2 /var # mount -o rw /dev/ada0p3 /usr .... Откройте файл [.filename]#/etc/fstab# и приведите его к изначальному виду: [.programlisting] .... /dev/ada0p2 /usr ufs rw 2 2 /dev/ada0p3 /var ufs rw 2 2 .... И напоследок, удалите строку, загружающую модуль `geom_journal`, из файла [.filename]#/boot/loader.conf# (или включите его опять, если он по прежнему требуется для других разделов диска), и перезагрузите операционную систему. === Как временно загрузиться без журналирования GEOM? Чтобы загрузить систему без журналирования GEOM, предотвратите загрузку модуля журнала во время запуска. Закомментируйте или удалите соответствующую строку из [.filename]#/boot/loader.conf# и перезагрузитесь: [.programlisting] .... geom_journal_load="YES" .... После загрузки без журналирования GEOM, журналируемые устройства (`*.journal`) не будут созданы. Файловые системы должны быть смонтированы с использованием их исходных (не журналируемых) провайдеров или вручную по мере необходимости для восстановления или обслуживания. Этот метод не изменяет метаданные журнала на диске и может безопасно использоваться для устранения неполадок. === Можно ли изменить размер журнала GEOM после его создания? -Нет. Журнал GEOM не может быть изменен в размере на месте после его создания. +Нет. Журнал GEOM не может быть изменён в размере на месте после его создания. Размер журнала фиксируется в момент выполнения `gjournal label` . Чтобы изменить размер журнала, необходимо удалить журналирование GEOM и переконфигурировать его с новым провайдером журнала желаемого размера. Для файловых систем, содержащих данные, это требует размонтирования файловой системы и воссоздания журнала с использованием провайдеров соответствующего размера, как описано ранее в этой статье. Планируйте размеры журналов консервативно, чтобы они соответствовали пиковой активности записи, так как изменение размера требует повторной инициализации конфигурации журнала. === Что происходит после некорректного завершения работы или сбоя питания? После некорректного завершения работы или сбоя питания, журналирование GEOM и Soft Updates с журналированием воспроизводят ожидающие записи журнала во время следующей загрузки, чтобы вернуть файловую систему в согласованное состояние. Если восстановление журнала завершается успешно, файловая система монтируется в обычном режиме, и полная проверка файловой системы не требуется. Восстановление журнала обычно занимает всего несколько секунд и зависит от объема недавней активности записи, а не от размера файловой системы. Полная проверка файловой системы может потребоваться в редких случаях, например, при обнаружении ошибок в устройстве хранения или несоответствии самого журнала. === Как взаимодействует журналирование GEOM с fsck? Журналирование GEOM и Soft Updates с журналированием взаимодействуют с `fsck_ffs(8)` различными способами, отражая их разные уровни интеграции в стеке хранения FreeBSD. Для журналирования GEOM восстановление после сбоя выполняется самой структурой GEOM. Во время запуска системы класс `geom_journal` обнаруживает метаданные журнала и воспроизводит все ожидающие записи журнала, пока провайдер обрабатывается GEOM, до того как журналируемое устройство станет видимым для более высоких уровней системы. Если воспроизведение журнала завершается успешно, файловая система возвращается в согласованное состояние, и суперблок UFS обновляется, чтобы указать, что проверка файловой системы не требуется. Когда позже во время загрузки вызывается `fsck_ffs(8)`, он считывает это состояние из суперблока и пропускает проверку файловой системы. Для Soft Updates с журналированием восстановление инициируется самим `fsck_ffs(8)`. Во время проверки файловой системы при загрузке, `fsck_ffs(8)` обнаруживает, что файловая система поддерживает Soft Updates с журналированием, и запускает логику воспроизведения журнала. Если воспроизведение журнала сообщает, что файловая система непротиворечива, `fsck_ffs(8)` завершается досрочно без выполнения полной проверки. Если воспроизведение журнала не может быть успешно завершено, выполняется традиционная проверка файловой системы. В результате, путь восстановления во время загрузки системы зависит от используемого механизма журналирования, что иллюстрируется следующей последовательностью загрузки: ---- Загрузчик системы | v Инициализация ядра | v Фреймворк GEOM framework (обнаружение поставщиков - tasting) | +--> Журналирование GEOM (gjournal) | - Выполнение записи на диск из журнала выполняется на этом этапе | - Согласованность файловой системы восстановлена | - Суперблок обновлен | v Фаза проверки файловой системы (fsck_ffs) | +--> Журналирование с Soft Updates | - Выполнение записи на диск из журнала, инициированное командой fsck | - fsck сразу выходит, если файловая система в согласованном состоянии | v Монтирование файловой системы | v Обычная работа системы ---- `fsck_ffs(8)` всё ещё используется, когда восстановление журнала не может быть завершено, при обнаружении ошибок базового хранилища или во время периодических ручных или запланированных проверок файловой системы. Журналирование GEOM сокращает время восстановления после сбоев, но не заменяет `fsck_ffs(8)` полностью. === Почему команда `gjournal clear` сообщает "Операция не разрешена" даже в однопользовательском режиме? В GEOM одно и то же базовое хранилище может быть представлено через несколько имён провайдеров одновременно. Например, раздел может быть виден как под своим именем, основанным на диске (например, `vtbd0p7`), так и под меткой GPT (например, `/dev/gpt/labelname`). Это разные провайдеры GEOM, ссылающиеся на одно и то же физическое хранилище. Когда команды `gjournal stop` или `gjournal clear` выполняются на одном имени провайдера, фреймворк GEOM может немедленно снова обнаружить метаданные журнала через другое имя провайдера в процессе распознавание устройства (tasting). В результате журнал автоматически повторно присоединяется, и попытки очистить его метаданные завершаются ошибкой "Операция не разрешена". Технически возможно подавить это поведение, отключив GEOM tasting или предотвратив создание альтернативных имён провайдеров, однако это крайне не рекомендуется. Такие изменения могут негативно повлиять на другие классы GEOM и системные компоненты, которые полагаются на обычное обнаружение провайдеров. По этой причине рекомендованная и безопасная процедура заключается в полной выгрузке модуля `geom_journal` перед удалением журнальных метаданных, как описано ранее в этой статье. При выгруженном модуле не происходит автоматического распознавания, и журнал не может быть повторно подключен, что позволяет команде `gjournal clear` завершиться успешно. === Можно ли использовать журналирование GEOM на корневой файловой системе? Да. Журналирование GEOM может использоваться на корневой файловой системе, но требует дополнительной осторожности при настройке системы. Модуль GEOM journal должен быть загружен на раннем этапе процесса загрузки, чтобы журналируемое корневое устройство было доступно до монтирования корневой файловой системы. Неправильная конфигурация может помешать системе загрузиться в обычном режиме, поэтому данная настройка, как правило, рекомендуется только опытным пользователям, которые полностью понимают последовательность загрузки и процедуры восстановления. По этим причинам журналирование GEOM чаще применяется к некорневым файловым системам, таким как `/usr` и `/var`. === Каковы последствия для производительности при использовании журналирования GEOM? Ведение журнала GEOM вводит дополнительные операции записи ввода-вывода, поскольку все операции записи сначала регистрируются в журнале перед фиксацией на устройстве хранения данных. Это приводит к увеличению задержки записи и более высокому коэффициенту увеличения объёма записи по сравнению с файловыми системами без журналирования. Производительность чтения обычно не страдает. Наиболее заметное влияние на производительность наблюдается при интенсивных нагрузках на запись и зависит от размера журнала, его размещения и скорости базового хранилища. Использование журнала достаточного размера и быстрого хранилища для поставщика журнала минимизирует потери в производительности. === Может ли журналирование GEOM использоваться вместе с другими классами GEOM? Да. GEOM журналирование может быть объединено с другими классами GEOM. При совместном использовании журналирование GEOM обычно работает поверх провайдеров, созданных другими классами GEOM, такими как `gmirror(8)` или `graid3(8)`. Порядок наложения важен и должен соответствовать задокументированным требованиям к слоям задействованных классов GEOM. GEOM журналирование обеспечивает целостность файловой системы на всех уровнях поставщиков, но не заменяет избыточность или обнаружение ошибок, предоставляемые другими классами GEOM. === Можно ли одновременно включить журналирование GEOM и Soft Updates? Нет. GEOM журналирование и Soft Updates не должны быть включены одновременно на одной файловой системе. GEOM журналирование требует исключительного контроля над порядком записи и гарантиями согласованности. Если Soft Updates включены вместе с GEOM журналированием, файловая система может вести себя непредсказуемо, и целостность данных не может быть гарантирована. При использовании журналирования GEOM необходимо отключить Soft Updates на затронутой файловой системе, как описано ранее в этой статье. [[soft-updates]] === В чем разница между Soft Updates и Soft Updates с журналированием? Как Soft Updates, так и Soft Updates with Journaling предназначены для поддержания целостности файловой системы, но используют разные механизмы и ведут себя по-разному после сбоя системы. _Soft Updates_ обеспечивают целостность за счёт тщательного упорядочивания записи метаданных в памяти, так что на диск записываются только безопасные состояния. При сбое любые обновления метаданных, ещё не записанные на диск, просто теряются, оставляя файловую систему в целостном, но, возможно, более старом состоянии. Однако учёт ресурсов может временно быть неточным, и для освобождения неиспользуемых блоков и индексных дескрипторов требуется полный запуск `fsck_ffs(8)`. _Soft Updates с журналированием_ расширяют функциональность _Soft Updates _, добавляя журнал метаданных, хранящийся в файловой системе. Изменения метаданных сначала записываются в журнал и автоматически воспроизводятся при следующей загрузке после некорректного завершения работы. Это позволяет быстро восстановить файловую систему в согласованное состояние, обычно без необходимости полного запуска `fsck_ffs(8)`. Короче говоря, _Soft Updates_ обеспечивают согласованность без журналирования, тогда как _Soft Updates с журналированием_ добавляют быстрое и автоматическое восстановление после сбоев ценой дополнительного дискового пространства и незначительного снижения производительности. [[further-reading]] == Для дальнейшего ознакомления Журналирование - относительно новая функциональная возможность FreeBSD, и она ещё недостаточно документирована. Однако, могут быть полезными следующие источники: * extref:{handbook}geom[Раздел Руководства FreeBSD, geom-gjournal], посвященный журналированию. * http://lists.freebsd.org/pipermail/freebsd-current/2006-June/064043.html[Этот пост] в списке рассылки {freebsd-current}, написанный `{pjd}` - автором man:gjournal[8]. * http://lists.freebsd.org/pipermail/freebsd-questions/2008-April/173501.html[Этот пост] от `{ivoras}` в списке рассылки {freebsd-questions}. * https://www.youtube.com/watch?v=_NuhRkiInvA[Journaled Soft-Updates, Dr. Kirk McKusick, BSDCan 2010] на YouTube * https://www.youtube.com/watch?v=xMpmOezBJZo[GEOM - in Infrastructure We Trust, Pawel Jakub Dawidek, AsiaBSDCon 2008] на YouTube * Страницы Справочника man:gjournal[8], man:geom[8] и man:tunefs[8]. diff --git a/documentation/content/ru/articles/gjournal-desktop/_index.po b/documentation/content/ru/articles/gjournal-desktop/_index.po index 70c3b72e0c..61c3bd74d0 100644 --- a/documentation/content/ru/articles/gjournal-desktop/_index.po +++ b/documentation/content/ru/articles/gjournal-desktop/_index.po @@ -1,3264 +1,3264 @@ # SOME DESCRIPTIVE TITLE # Copyright (C) YEAR The FreeBSD Project # This file is distributed under the same license as the FreeBSD Documentation package. # Vladlen Popolitov , 2025, 2026. msgid "" msgstr "" "Project-Id-Version: FreeBSD Documentation VERSION\n" "POT-Creation-Date: 2026-02-22 15:58+0000\n" -"PO-Revision-Date: 2026-03-08 09:11+0000\n" +"PO-Revision-Date: 2026-05-11 04:45+0000\n" "Last-Translator: Vladlen Popolitov \n" "Language-Team: Russian \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "X-Generator: Weblate 4.17\n" #. type: Title = #: documentation/content/en/articles/gjournal-desktop/_index.adoc:1 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:13 #, no-wrap msgid "Implementing UFS Journaling on a Desktop PC" msgstr "Настройка журналирования UFS для настольного компьютера" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:46 msgid "Abstract" msgstr "Аннотация" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:52 msgid "" "A journaling file system uses a log to record file system updates and " "preserves consistency in the event of a system crash or power failure. " "Although unsaved changes to files may still be lost, journaling greatly " "reduces the risk of file system corruption caused by an unclean shutdown and " "significantly shortens recovery time. While the UFS file system employed by " "FreeBSD does not implement journaling as an inherent on-disk feature, " "FreeBSD provides journaling support through file system-level mechanisms " "(Soft Updates with journaling) as well as through the GEOM framework " "(`gjournal`). This article describes the available UFS journaling " "mechanisms and explains their appropriate use on modern FreeBSD systems. " "_The content has been reviewed and updated for FreeBSD versions 13 through " "15_." msgstr "" "Журналируемая файловая система использует журнал для записи обновлений " "файловой системы и обеспечивает целостность данных в случае сбоя системы или " "отключения питания. Несмотря на то, что несохранённые изменения в файлах всё " "ещё могут быть утеряны, журналирование значительно снижает риск повреждения " "файловой системы из-за некорректного завершения работы и существенно " "сокращает время восстановления. Хотя файловая система UFS, используемая в " "FreeBSD, не реализует журналирование как встроенную функцию на уровне диска, " "FreeBSD предоставляет поддержку журналирования через механизмы на уровне " "файловой системы (Soft Updates с журналированием), а также через фреймворк " "GEOM (`gjournal`). В этой статье описываются доступные механизмы " "журналирования UFS и объясняется их целесообразное использование в " "современных системах FreeBSD. _Содержание было проверено и обновлено для " "версий FreeBSD с 13 по 15_." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:54 msgid "'''" msgstr "'''" #. type: Title == #: documentation/content/en/articles/gjournal-desktop/_index.adoc:58 #, no-wrap msgid "Introduction" msgstr "Введение" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:63 msgid "" "While professional servers are usually well protected from unforeseen " "shutdowns, the typical desktop is at the mercy of power failures, accidental " "resets, and other user related incidents that can lead to unclean shutdowns " "and leave a file system in an inconsistent state. Traditionally, this " "required running `fsck`, which on large file systems could take a " "significant amount of time. On rare occasions, file system corruption " "reaches a point where user intervention is required and data may be lost." msgstr "" "Серверное оборудование обычно хорошо защищено от потери питания. Настольный " "компьютер часто подвержен неожиданным пропаданиям питания, случайным " "нажатиям кнопки Reset и другим происшествиям (часто связанным с " "неосторожностью пользователей), которые могут привести к непредвиденным " "выключениям и оставить файловую систему в несогласованном состоянии. " "Традиционно это требовало запуска `fsdk`, что на больших файловых системах " "требует значительного времени. В очень редких случаях повреждения файловой " "системы достигают того уровня, при котором становится необходимым " "вмешательство пользователя и данные могут быть утерянными." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:65 msgid "" "FreeBSD provides two distinct journaling mechanisms for the UFS file system:" msgstr "" "FreeBSD предоставляет два различных механизма журналирования для файловой " "системы UFS:" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:67 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:155 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:158 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:161 #, no-wrap msgid "Soft Updates with journaling" msgstr "Журналирование с Soft Updates" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:68 msgid "GEOM journaling (`gjournal`)" msgstr "Журналирование с командой GEOM `gjournal`" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:70 msgid "" "These mechanisms operate at different layers of the system and have " "different performance and semantic characteristics." msgstr "" "Эти механизмы функционируют на различных уровнях системы и обладают разными " "характеристиками производительности и семантики." #. type: delimited block = 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:74 msgid "" "For most modern FreeBSD systems, including desktops and general-purpose " "servers, *Soft Updates with journaling* is the recommended solution." msgstr "" "Для большинства современных систем FreeBSD, включая настольные компьютеры и " "серверы общего назначения, рекомендуется использовать *Soft Updates с " "журналированием*." #. type: delimited block = 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:76 msgid "" "GEOM journaling is a legacy and specialized mechanism and should only be " "used when its specific semantics are required." msgstr "" "GEOM журналирование — это устаревший и специализированный механизм, и его " "следует использовать только тогда, когда требуются его специфические " "семантики." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:79 msgid "" "This article explains both mechanisms, their differences, and correct modern " "usage." msgstr "" "В этой статье объясняются оба механизма, их различия и правильное " "современное использование." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:81 msgid "Read this chapter to learn:" msgstr "Прочтите эту главу, чтобы узнать:" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:83 msgid "" "The journaling mechanisms available for the UFS file system in FreeBSD and " "how they differ." msgstr "" "Доступные механизмы журналирования для файловой системы UFS в FreeBSD и их " "различия." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:84 msgid "" "When to use file system-level Soft Updates journaling and when GEOM " "journaling may be appropriate." msgstr "" "Когда использовать журналирование на уровне файловой системы с Soft Updates " "и когда может быть уместно журналирование GEOM." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:85 msgid "" "How to enable or disable Soft Updates journaling on existing UFS file " "systems." msgstr "" "Как включить или отключить журналирование Soft Updates на существующих " "файловых системах UFS." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:86 msgid "" "How to configure GEOM journaling on new or existing partitions, including " "required kernel support and journal sizing considerations." msgstr "" "Как настроить журналирование GEOM на новых или существующих разделах, " "включая необходимую поддержку ядра и вопросы определения размера журнала." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:87 msgid "" "What configuration changes are required to mount journaled file systems and " "how journaling affects system behavior." msgstr "" "Какие изменения конфигурации необходимы для монтирования журналируемых " "файловых систем и как журналирование влияет на поведение системы." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:88 msgid "How to diagnose and resolve common issues related to UFS journaling." msgstr "" "Как диагностировать неполадки и разрешать проблемы, связанные с " "журналированием файловой системы UFS." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:90 msgid "Before reading this article:" msgstr "Перед прочтением этой статьи вам необходимо:" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:92 msgid "Understand basic UNIX(R) and FreeBSD concepts." msgstr "" "Понимать базовые концепции таких операционных систем, как UNIX(R) и FreeBSD." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:93 msgid "Be familiar with the FreeBSD installation process using bsdinstall." msgstr "Быть знакомым с процедурой установки FreeBSD, используя bsdinstall." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:94 msgid "" "Have basic knowledge of disk partitioning and file systems, including tools " "such as gpart(8), newfs(8), and mount(8)." msgstr "" "Иметь базовые знания о разбиении дисков и файловых системах, включая такие " "инструменты, как gpart(8), newfs(8) и mount(8)." #. type: delimited block = 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:99 msgid "" "Some of the procedures described in this article involve modifying file " "system or disk configuration and may require unmounting file systems or " "changing on-disk metadata. Before making such changes on a system in " "production, ensure that reliable _backups_ of all important data are " "available." msgstr "" "Некоторые процедуры, описанные в данной статье, включают изменение " "конфигурации файловой системы или диска и могут потребовать размонтирования " "файловых систем или изменения метаданных на диске. Перед внесением подобных " "изменений в работающей системе убедитесь, что доступны надежные _резервные " "копии_ всех важных данных." #. type: delimited block = 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:102 msgid "" "Enabling file system-level Soft Updates journaling is generally safe and " "does not require disk repartitioning. However, configuring GEOM journaling " "involves low-level disk operations and should be attempted only by " "experienced administrators who fully understand the implications." msgstr "" "Включение журналирования Soft Updates на уровне файловой системы обычно " "безопасно и не требует переразбивки диска. Однако настройка журналирования " "GEOM включает низкоуровневые операции с диском и должна выполняться только " "опытными администраторами, полностью понимающими последствия." #. type: Title == #: documentation/content/en/articles/gjournal-desktop/_index.adoc:105 #, no-wrap msgid "Understanding Journaling in FreeBSD" msgstr "Реализация журналирования в FreeBSD" #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:107 #, no-wrap msgid "Soft Updates with Journaling (Recommended)" msgstr "Soft Updates с журналированием (рекомендуется)" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:109 msgid "" "Soft Updates is the default UFS consistency mechanism in FreeBSD. When " "combined with journaling, it provides *metadata journaling* within the file " "system itself." msgstr "" "Soft Updates — это механизм обеспечения согласованности UFS по умолчанию в " "FreeBSD. В сочетании с журналированием он обеспечивает *журналирование " "метаданных* в самой файловой системе." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:111 msgid "Advantages of Soft Updates with journaling include:" msgstr "Преимущества Soft Updates с журналированием включают:" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:113 msgid "Very fast crash recovery (typically seconds)" msgstr "Очень быстрое восстановление после сбоя (обычно за секунды)" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:114 msgid "Normal `sync(2)` and `fsync(2)` semantics" msgstr "Обычная семантика `sync(2)` и `fsync(2)`" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:115 msgid "No additional partitions or GEOM layers" msgstr "Никаких дополнительных разделов или слоев GEOM" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:116 msgid "Simple configuration and maintenance" msgstr "Простая настройка и обслуживание" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:118 msgid "From `tunefs(8)`:" msgstr "Из `tunefs(8)`:" #. type: delimited block _ 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:121 msgid "" "Enabling journaling reduces the time spent by fsck_ffs(8) cleaning up a file " "system after a crash to a few seconds from minutes to hours." msgstr "" "Включение журналирования сокращает время, затрачиваемое fsck_ffs(8) на " "очистку файловой системы после сбоя, с нескольких минут или часов до " "нескольких секунд." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:124 msgid "" "This mechanism is suitable for nearly all UFS-based systems and is the " "default recommendation." msgstr "" "Этот механизм подходит практически для всех систем на основе UFS и является " "рекомендуемым по умолчанию." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:125 #, no-wrap msgid "GEOM Journaling (`gjournal`)" msgstr "Журналирование с командой GEOM `gjournal`" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:128 msgid "" "GEOM journaling operates at the block level, below the file system. It " "journals all block writes, including *both metadata and file data*." msgstr "" "GEOM журналирование работает на блочном уровне, ниже файловой системы. Оно " "журналирует все записи блоков, включая *как метаданные, так и данные файлов*." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:130 msgid "Key characteristics of GEOM journaling:" msgstr "Ключевые характеристики журналирования GEOM:" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:132 msgid "Implemented as a GEOM class (`geom_journal`)" msgstr "Реализовано как класс GEOM (`geom_journal`)" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:133 msgid "Journals all block I/O, not just metadata" msgstr "Журналирует весь блочный ввод-вывод, а не только метаданные" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:134 msgid "Requires explicit cooperation from UFS using the `-J` flag" msgstr "Требует явного согласования от UFS с использованием флага `-J`" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:135 msgid "Disables Soft Updates" msgstr "Отключает Soft Updates" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:136 msgid "Alters the semantics of `sync(2)` and `fsync(2)`" msgstr "Изменяет семантику `sync(2)` и `fsync(2)`" #. type: delimited block = 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:140 msgid "" "On GEOM-journaled file systems, `sync(2)` and `fsync(2)` do not guarantee " "that data has been committed to stable storage. To ensure persistence, " "`gjournal sync` must be used." msgstr "" "На файловых системах с журналированием GEOM, `sync(2)` и `fsync(2)` не " "гарантируют, что данные были записаны на постоянное хранилище. Для " "обеспечения сохранности необходимо использовать `gjournal sync`." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:143 msgid "" "Because of these differences, GEOM journaling is not recommended for general-" "purpose desktop or server use." msgstr "" "Из-за этих различий журналирование GEOM не рекомендуется для общего " "использования на настольных компьютерах или серверах." #. type: Title == #: documentation/content/en/articles/gjournal-desktop/_index.adoc:144 #, no-wrap msgid "Choosing the Appropriate Journaling Method" msgstr "Выбор подходящего метода журналирования" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:147 msgid "The following table summarizes recommended usage:" msgstr "В следующей таблице приведены рекомендуемые варианты использования:" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:150 #, no-wrap msgid "Use case" msgstr "Вариант использования" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:152 #, no-wrap msgid "Recommended mechanism" msgstr "Рекомендуемый механизм" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:153 #, no-wrap msgid "Desktop or laptop system" msgstr "Настольная или портативная система" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:156 #, no-wrap msgid "General-purpose server" msgstr "Универсальный сервер" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:159 #, no-wrap msgid "Legacy UFS systems" msgstr "Устаревшие системы UFS" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:162 #, no-wrap msgid "File system-independent journaling requirements" msgstr "Требования к журналированию, не зависящие от файловой системы" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:164 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:166 #, no-wrap msgid "GEOM journaling" msgstr "Журналирование GEOM" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:165 #, no-wrap msgid "Specialized block-level logging needs" msgstr "Специализированное журналирование на уровне блоков" #. type: Title == #: documentation/content/en/articles/gjournal-desktop/_index.adoc:168 #, no-wrap msgid "Using Soft Updates with Journaling" msgstr "Использование Soft Updates с журналированием" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:173 msgid "" "Soft Updates with journaling provide file system-level journaling for UFS. " "This mechanism preserves file system consistency while retaining the " "allocation and ordering optimizations of Soft Updates. Unlike GEOM " "journaling, no separate journal device or partition is required." msgstr "" "Soft Updates с журналированием обеспечивают журналирование на уровне " "файловой системы для UFS. Этот механизм сохраняет целостность файловой " "системы, одновременно сохраняя оптимизации выделения и упорядочивания, " "характерные для Soft Updates. В отличие от журналирования GEOM, отдельное " "журналирующее устройство или раздел не требуется." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:174 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:254 #, no-wrap msgid "Overview" msgstr "Обзор" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:179 msgid "" "Soft Updates with journaling record file system metadata changes in a " "journal stored inside the file system itself, implemented as a hidden file " "named [.filename]#.sujournal# in the root of the file system. In the event " "of a crash or power failure, pending metadata operations are replayed from " "the journal, allowing the file system to be mounted quickly without a full " "consistency check." msgstr "" "Soft Updates с журналированием записывают изменения метаданных файловой " "системы в журнал, хранящийся внутри самой файловой системы, реализованный " "как скрытый файл с именем [.filename]#.sujournal# в корне файловой системы. " "В случае сбоя или отключения питания ожидающие операции с метаданными " "воспроизводятся из журнала, что позволяет быстро смонтировать файловую " "систему без полной проверки согласованности." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:182 msgid "" "This form of journaling applies to file system metadata only. File data " "integrity remains the responsibility of applications." msgstr "" "Эта форма журналирования применяется только к метаданным файловой системы. " "Целостность данных файлов остается ответственностью приложений." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:183 #, no-wrap msgid "Enabling Journaling on an Existing File System" msgstr "Включение журналирования на существующей файловой системе" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:186 msgid "" "The file system must be unmounted or mounted read-only before changing " "journaling settings." msgstr "" "Файловая система должна быть размонтирована или смонтирована в режиме только " "для чтения перед изменением настроек журналирования." #. type: delimited block - 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:192 #, no-wrap msgid "" "# umount /usr\n" "# tunefs -n enable -j enable /dev/ada0p2\n" "# mount /usr\n" msgstr "" "# umount /usr\n" "# tunefs -n enable -j enable /dev/ada0p2\n" "# mount /usr\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:195 msgid "" "No additional configuration is required. Standard mount options may be used." msgstr "" "Дополнительная настройка не требуется. Можно использовать стандартные " "параметры монтирования." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:196 #, no-wrap msgid "Journal Storage and Size" msgstr "Хранение журналов и их размер" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:200 msgid "" "A default journal size is selected automatically when journaling is " "enabled. In most cases, the default size is sufficient and does not require " "adjustment." msgstr "" "Размер журнала по умолчанию выбирается автоматически при включении ведения " "журнала. В большинстве случаев размер по умолчанию достаточен и не требует " "корректировки." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:202 msgid "" "If necessary, the journal size in bytes can be specified explicitly using " "the `-S` option to `tunefs(8)`:" msgstr "" "При необходимости размер журнала в байтах может быть явно указан с помощью " "опции `-S` для `tunefs(8)`:" #. type: delimited block - 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:206 #, no-wrap msgid "# tunefs -S 64000000 /dev/ada0p2\n" msgstr "# tunefs -S 64000000 /dev/ada0p2\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:209 msgid "" "Journal size tuning is rarely required and should be considered only for " "file systems with unusually high metadata update rates." msgstr "" "Настройка размера журнала редко требуется и должна рассматриваться только " "для файловых систем с необычно высокой частотой обновления метаданных." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:210 #, no-wrap msgid "Checking Soft Updates with Journaling" msgstr "Проверка Soft Updates с журналированием" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:213 msgid "" "The journaling status of a UFS file system using Soft Updates can be " "verified with `tunefs(8)` or `dumpfs(8)`." msgstr "" "Статус журналирования файловой системы UFS с использованием Soft Updates " "можно проверить с помощью `tunefs(8)` или `dumpfs(8)`." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:215 msgid "To display the current file system settings, run:" msgstr "Чтобы отобразить текущие настройки файловой системы, выполните:" #. type: delimited block - 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:221 #, no-wrap msgid "" "# tunefs -p /dev/ada0p2 | grep -i journal\n" "tunefs: soft updates journaling: (-j) enabled\n" "tunefs: gjournal: (-J) disabled\n" msgstr "" "# tunefs -p /dev/ada0p2 | grep -i journal\n" "tunefs: soft updates journaling: (-j) enabled\n" "tunefs: gjournal: (-J) disabled\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:224 msgid "Look for the following indicators in the output:" msgstr "Ищите следующие индикаторы в выводе:" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:226 msgid "Soft Updates enabled" msgstr "Soft Updates включены" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:227 msgid "Soft Updates journaling enabled" msgstr "Soft Updates с журналированием включены" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:229 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:644 msgid "" "Alternatively, `dumpfs(8)` can be used to inspect the file system superblock:" msgstr "" "Или для проверки суперблока файловой системы можно использовать `dumpfs(8)`:" #. type: delimited block - 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:234 #, no-wrap msgid "" "# dumpfs /dev/ada0p2 | grep -i journal\n" "flags soft-updates+journal\n" msgstr "" "English type: delimited block - 4\n" "# dumpfs /dev/ada0p2 | grep -i journal\n" "flags soft-updates+journal\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:237 msgid "These commands are read-only and do not modify file system state." msgstr "" "Эти команды предназначены только для чтения и не изменяют состояние файловой " "системы." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:238 #, no-wrap msgid "File System Checks and Maintenance" msgstr "Проверка и обслуживание файловой системы" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:241 msgid "" "Although journaling dramatically reduces recovery time after a crash, it " "does not eliminate the need for periodic full file system checks." msgstr "" "Хотя журналирование значительно сокращает время восстановления после сбоя, " "оно не устраняет необходимость периодических полных проверок файловой " "системы." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:243 msgid "Journaling guarantees consistency, not correctness" msgstr "Журналирование гарантирует целостность, а не корректность" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:244 msgid "Media errors are not repaired by journaling" msgstr "Ошибки носителя не исправляются журналированием" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:245 msgid "Periodic `fsck` should still be scheduled" msgstr "Периодическая проверка `fsck` все еще должна быть запланирована" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:246 msgid "Background `fsck` can be used on live file systems" msgstr "Фоновый `fsck` может использоваться на работающих файловых системах" #. type: Title == #: documentation/content/en/articles/gjournal-desktop/_index.adoc:247 #, no-wrap msgid "Using GEOM Journaling (Advanced)" msgstr "Использование журналирования GEOM (Продвинутый уровень)" #. type: delimited block = 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:252 msgid "" "This section is intended for advanced users who understand the implications " "of block-level journaling and altered sync semantics." msgstr "" "Данный раздел предназначен для опытных пользователей, которые понимают " "последствия журналирования на уровне блоков и изменения семантики " "синхронизации." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:259 msgid "" "This functionality is provided by loading the [.filename]#geom_journal.ko# " "module into the kernel (or building it into a custom kernel) and using the " "`gjournal` command to configure the file systems. In general, you would " "like to journal large file systems, like [.filename]#/usr#. You will need " "however (see the following section) to reserve some free disk space." msgstr "" "Возможность журналирования обеспечивается загрузкой модуля [." "filename]#geom_journal.ko# в ядро (или сборкой собственного ядра с " "активированием соответствующих опций) и использованием команды `gjournal` " "для конфигурирования файловой системы. В общем, вы предпочтете журналировать " "файловые системы большого размера, к примеру - [.filename]#/usr#. Однако, " "вам придется зарезервировать некоторое количество свободного места (см. " "следующий раздел)." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:262 msgid "" "GEOM journaling is implemented by the `geom_journal` kernel module and is " "configured using the `gjournal(8)` utility. It provides block-level " "journaling below the file system layer and requires explicit cooperation " "from UFS." msgstr "" "Журналирование GEOM реализовано модулем ядра `geom_journal` и настраивается " "с помощью утилиты `gjournal(8)`. Оно обеспечивает журналирование на уровне " "блоков ниже слоя файловой системы и требует явной поддержки со стороны UFS." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:265 msgid "" "When GEOM journaling is used, some disk space is needed to keep the journal " "itself. The provider that contains the file system data is referred to as " "the _data provider_, while the provider that stores the journal is referred " "to as the _journal provider_." msgstr "" "При использовании журналирования GEOM требуется некоторое дисковое " "пространство для хранения самого журнала. Провайдер, содержащий данные " "файловой системы, называется _провайдером данных_, а провайдер, хранящий " "журнал, называется _провайдером журнала_." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:270 msgid "" "When journaling an existing (non-empty) file system, the data and journal " "providers must be separate. When journaling a new, empty file system, a " "single provider may be used to store both data and journal information. In " "both cases, `gjournal(8)` combines the data and journal providers to create " "a new journaled provider, which is then mounted by the file system. For " "example:" msgstr "" "При журналировании существующей (непустой) файловой системы провайдеры " "данных и журнала должны быть раздельными. При журналировании новой, пустой " "файловой системы, один провайдер может использоваться для хранения как " "данных, так и информации журнала. В обоих случаях `gjournal(8)` объединяет " "провайдеры данных и журнала для создания нового журналируемого провайдера, " "который затем монтируется файловой системой. Например:" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:272 msgid "" "The `/usr` file system resides on `/dev/ada0p2` and already contains data." msgstr "" "Файловая система `/usr` расположена на `/dev/ada0p2` и уже содержит данные." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:273 msgid "" "Free disk space has been allocated in a separate partition, `/dev/ada0p4`, " "to hold the journal." msgstr "" "Свободное дисковое пространство выделено в отдельном разделе, `/dev/ada0p4`, " "для хранения журнала." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:275 msgid "" "After configuring GEOM journaling, a new provider `/dev/ada0p2.journal` is " "created. This journaled provider combines `/dev/ada0p2` as the data " "provider and `/dev/ada0p4` as the journal provider and is used for all " "subsequent file system operations." msgstr "" -"После настройки журналирования GEOM создается новый провайдер `/dev/ada0p2." +"После настройки журналирования GEOM создаётся новый провайдер `/dev/ada0p2." "journal`. Этот журналируемый провайдер объединяет `/dev/ada0p2` в качестве " "провайдера данных и `/dev/ada0p4` в качестве провайдера журнала и " "используется для всех последующих операций файловой системы." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:278 msgid "" "The amount of disk space required for the journal depends primarily on the " "write workload of the file system rather than on the size of the data " "provider. Systems with sustained or bursty write activity require larger " "journals to avoid excessive journal switching or write throttling." msgstr "" "Объем дискового пространства, необходимого для журнала, в первую очередь " "зависит от интенсивности записи в файловую систему, а не от размера " "поставщика данных. Системам с постоянной или импульсной активностью записи " "требуются журналы большего размера, чтобы избежать чрезмерного переключения " "журналов или ограничения записи." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:280 msgid "From the man page `gjournal(8)`:" msgstr "Из справочной страницы `gjournal(8)`:" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:282 msgid "The default journal size is 1 GB." msgstr "Размер журнала по умолчанию составляет 1 ГБ." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:283 msgid "" "The recommended minimum journal size is twice the amount of installed " "physical memory." msgstr "" "Рекомендуемый минимальный размер журнала составляет удвоенный объем " "установленной оперативной памяти." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:284 msgid "" "The journal size should be chosen based on expected write load, not file " "system size." msgstr "" "Размер журнала должен выбираться на основе ожидаемой нагрузки записи, а не " "размера файловой системы." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:286 msgid "" "An undersized journal may result in degraded performance or forced journal " "switches under heavy write load." msgstr "" "Недостаточный размер журнала может привести к снижению производительности " "или вынужденным переключениям журнала при высокой нагрузке на запись." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:288 msgid "" "For more information about journaling, please read the manual page of man:" "gjournal[8]." msgstr "" "Для получения дополнительной информации о журналировании, пожалуйста, " "прочитайте страницу справочника, посвященную man:gjournal[8]." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:290 #, no-wrap msgid "Steps During the Installation of FreeBSD" msgstr "Действия, необходимые во время установки FreeBSD" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:294 msgid "" "This section describes optional installation-time preparation for systems " "that are configured to use GEOM journaling. The goal is to reserve disk " "space for journal providers that will later be associated with the `/usr` " "and `/var` file systems." msgstr "" "В этом разделе описывается необязательная подготовка во время установки для " "систем, настроенных на использование журналирования GEOM. Цель — " "зарезервировать дисковое пространство для журнальных провайдеров, которые " "впоследствии будут связаны с файловыми системами `/usr` и `/var`." #. type: Title ==== #: documentation/content/en/articles/gjournal-desktop/_index.adoc:295 #, no-wrap msgid "Reserving Space for Journaling" msgstr "Выделение места под журналирование" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:299 msgid "" "On a typical system with a single disk, the operating system, installed " "software, and user data all reside on the same device. The default " "automatic partitioning performed by the FreeBSD installer allocates most " "available space to `/usr`, with smaller partitions for `/var` and other " "mount points." msgstr "" "На типичной системе с одним диском операционная система, установленное " "программное обеспечение и пользовательские данные находятся на одном " "устройстве. Стандартное автоматическое разбиение, выполняемое установщиком " "FreeBSD, выделяет большую часть доступного пространства под `/usr`, с " "меньшими разделами для `/var` и других точек монтирования." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:303 msgid "" "By default, the installer allocates all available disk space to file systems " "and does not leave unused space. When GEOM journaling is planned for " "existing (non-empty) file systems, additional disk space must be reserved to " "hold journal providers. Each file system that will be journaled requires " "its own journal provider." msgstr "" "По умолчанию установщик выделяет всё доступное дисковое пространство для " "файловых систем и не оставляет неиспользуемого места. Если планируется " "использование журналирования GEOM для существующих (непустых) файловых " "систем, необходимо зарезервировать дополнительное дисковое пространство для " "размещения журнальных провайдеров. Каждая файловая система, которая будет " "журналироваться, требует собственного журнального провайдера." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:305 msgid "" "Since `/usr` typically occupies the largest portion of the disk, it is " "usually the most practical partition to reduce slightly in order to make " "room for journal providers." msgstr "" "Поскольку `/usr` обычно занимает наибольшую часть диска, это наиболее " "практичный раздел для небольшого уменьшения, чтобы освободить место для " "журналируемых провайдеров." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:307 msgid "In our example GEOM journaling is planned for both `/usr` and `/var`." msgstr "" "В нашем примере журналирование GEOM планируется как для `/usr`, так и для " "`/var`." #. type: Title ==== #: documentation/content/en/articles/gjournal-desktop/_index.adoc:308 #, no-wrap msgid "Partitioning Strategy" msgstr "Стратегия разбиения на разделы" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:312 msgid "" "During installation, use the manual partitioning mode provided by the " "installer. Create any supported file system type for `/`, and create " "standard UFS partitions for `/usr` and `/var`, but reduce the size of `/usr` " "to leave sufficient unallocated space at the end of the disk." msgstr "" "Во время установки используйте режим ручного разбиения, предоставляемый " "установщиком. Создайте любую поддерживаемую файловую систему для `/`, а " "также стандартные разделы UFS для `/usr` и `/var`, но уменьшите размер `/usr`" ", чтобы оставить достаточно нераспределенного пространства в конце диска." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:314 msgid "" "From the remaining unallocated space, create two additional partitions that " "will be used exclusively as journal providers:" msgstr "" "Из оставшегося нераспределенного пространства создайте два дополнительных " "раздела, которые будут использоваться исключительно в качестве журнальных " "провайдеров:" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:316 msgid "One partition for the `/usr` journal" msgstr "Один раздел для журнала `/usr`" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:317 msgid "One partition for the `/var` journal" msgstr "Один раздел для журнала `/var`" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:320 msgid "" "These partitions must not be assigned mount points and must not be used for " "swap. They will remain unused until they are explicitly associated with " "their corresponding data providers using `gjournal(8)` after installation." msgstr "" "Эти разделы не должны иметь назначенных точек монтирования и не должны " "использоваться для подкачки. Они останутся неиспользованными до тех пор, " "пока не будут явно связаны с соответствующими поставщиками данных с помощью " "`gjournal(8)` после установки." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:322 msgid "A typical layout may look like the following:" msgstr "Типичная схема может выглядеть следующим образом:" #. type: Block title #: documentation/content/en/articles/gjournal-desktop/_index.adoc:323 #, no-wrap msgid "Partitions Reserved for GEOM Journaling" msgstr "Разделы, Зарезервированные для Журналирования GEOM" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:327 #, no-wrap msgid "Provider" msgstr "Поставщик" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:328 #, no-wrap msgid "Intended Use" msgstr "Предназначение" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:330 #, no-wrap msgid "Notes" msgstr "Заметки" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:331 #, no-wrap msgid "/dev/ada0p2" msgstr "/dev/ada0p2" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:332 #, no-wrap msgid "/var" msgstr "/var" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:334 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:338 #, no-wrap msgid "UFS file system (data provider)" msgstr "Файловая система UFS (поставщик данных)" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:335 #, no-wrap msgid "/dev/ada0p3" msgstr "/dev/ada0p3" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:336 #, no-wrap msgid "/usr" msgstr "/usr" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:339 #, no-wrap msgid "/dev/ada0p4" msgstr "/dev/ada0p4" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:340 #, no-wrap msgid "Journal for /var" msgstr "Журнал для /var" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:342 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:345 #, no-wrap msgid "Unformatted, unused partition" msgstr "Неформатированный, неиспользуемый раздел" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:343 #, no-wrap msgid "/dev/ada0p5" msgstr "/dev/ada0p5" #. type: Table #: documentation/content/en/articles/gjournal-desktop/_index.adoc:344 #, no-wrap msgid "Journal for /usr" msgstr "Журнал для /usr" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:349 msgid "" "The exact device names will vary depending on the disk layout and " "partitioning scheme. It is strongly recommended to record the provider " "names during installation, as they will be required during journal " "configuration." msgstr "" "Точные названия устройств могут различаться в зависимости от структуры диска " "и схемы разделов. Настоятельно рекомендуется записать имена провайдеров во " "время установки, так как они потребуются при настройке журнала." #. type: Title ==== #: documentation/content/en/articles/gjournal-desktop/_index.adoc:350 #, no-wrap msgid "Journal Size Considerations" msgstr "Соображения по размеру журнала" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:355 msgid "" "Journal size depends on the expected write workload rather than on the size " "of the file system. For general-purpose systems, journal sizes of 1–2 GB " "are commonly sufficient. Systems with sustained or bursty write activity " "may require larger journals." msgstr "" "Размер журнала зависит от ожидаемой нагрузки на запись, а не от размера " "файловой системы. Для систем общего назначения обычно достаточно журналов " "размером 1–2 ГБ. Системам с постоянной или импульсной активностью записи " "могут потребоваться журналы большего размера." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:357 msgid "" "Allocate journal space conservatively during installation, as resizing " "partitions later may require additional downtime." msgstr "" "Выделяйте пространство под журнал экономно во время установки, так как " "изменение размера разделов позже может потребовать дополнительного времени " "простоя." #. type: Title ==== #: documentation/content/en/articles/gjournal-desktop/_index.adoc:358 #, no-wrap msgid "Completing the Installation" msgstr "Завершение инсталляции" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:362 msgid "" "After reserving the required partitions, complete the FreeBSD installation " "normally. It is recommended to postpone the installation of third-party " "software and additional system configuration until GEOM journaling has been " "fully configured." msgstr "" "После резервирования необходимых разделов завершите установку FreeBSD в " "обычном режиме. Рекомендуется отложить установку стороннего программного " "обеспечения и дополнительную настройку системы до полной настройки " "журналирования GEOM." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:365 msgid "" "At this stage, the system will boot using the standard UFS file systems. " "The reserved journal partitions will remain unused until journaling is " "explicitly enabled." msgstr "" "На этом этапе система загрузится с использованием стандартных файловых " "систем UFS. Зарезервированные журнальные разделы останутся неиспользованными " "до тех пор, пока журналирование не будет явно включено." #. type: Title ==== #: documentation/content/en/articles/gjournal-desktop/_index.adoc:367 #, no-wrap msgid "First Boot After Installation" msgstr "Первая загрузка после установки" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:371 msgid "" "After the first successful boot, no immediate configuration changes are " "required. The system should be verified to boot and operate normally before " "proceeding." msgstr "" "После первого успешного запуска немедленные изменения конфигурации не " "требуются. Следует убедиться, что система загружается и работает нормально, " "прежде чем продолжить." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:373 msgid "" "Once the base system is confirmed to be functional, the next steps involve:" msgstr "" "После того, как подтверждено, что базовая система работоспособна, следующие " "шаги включают:" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:375 msgid "Loading or enabling GEOM journaling support" msgstr "Загрузка или включение поддержки журналирования GEOM" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:376 msgid "Associating journal providers with their corresponding data providers" msgstr "" "Связывание журнальных провайдеров с соответствующими провайдерами данных" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:377 msgid "Updating `/etc/fstab` to mount the journaled devices" msgstr "Обновление `/etc/fstab` для монтирования журналируемых устройств" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:379 msgid "These steps are described in the following section." msgstr "Эти шаги описаны в следующем разделе." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:381 #, no-wrap msgid "Setting Up Journaling" msgstr "Настройка журналирования" #. type: Title ==== #: documentation/content/en/articles/gjournal-desktop/_index.adoc:384 #, no-wrap msgid "Enabling GEOM Journaling on Existing File Systems" msgstr "Включение журналирования GEOM в существующих файловых системах" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:387 msgid "" "This section describes how to enable GEOM journaling on the `/usr` and `/" "var` file systems using the partitions prepared during installation." msgstr "" "В этом разделе описывается, как включить журналирование GEOM для файловых " "систем `/usr` и `/var`, используя разделы, подготовленные в процессе " "установки." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:390 msgid "" "Once the required journal providers have been reserved, GEOM journaling can " "be configured. Because the file systems to be journaled must not be " "mounted, the system must be switched to single-user mode." msgstr "" "После резервирования необходимых журнальных провайдеров можно настроить " "журналирование GEOM. Поскольку файловые системы, подлежащие журналированию, " "не должны быть смонтированы, систему необходимо переключить в " "однопользовательский режим." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:392 msgid "Log in as `root` and enter:" msgstr "Залогиньтесь `root` и введите:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:396 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:719 #, no-wrap msgid "# shutdown now\n" msgstr "# shutdown now\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:401 msgid "" "Press kbd:[Enter] to obtain a root shell. Unmount the file systems that " "will be journaled. In this example, `/usr` and `/var`:" msgstr "" "Нажмите kbd:[Enter] для получения приглашения командного интерпретатора в " "режиме root. Нам необходимо будет размонтировать разделы, которые подлежат " "журналированию, в нашем примере это [.filename]#/usr# и [.filename]#/var#:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:405 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:726 #, no-wrap msgid "# umount /usr /var\n" msgstr "# umount /usr /var\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:408 msgid "Load the GEOM journaling kernel module:" msgstr "Загрузите модуль ядра GEOM journaling:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:412 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:691 #, no-wrap msgid "# gjournal load\n" msgstr "# gjournal load\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:416 msgid "" "Next, associate each data provider with its corresponding journal provider. " "Use your notes to determine which partition will be used for each journal." msgstr "" "Далее, свяжите каждого поставщика данных с соответствующим поставщиком " "журналов. Используйте свои заметки, чтобы определить, какой раздел будет " "использоваться для каждого журнала." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:418 msgid "In this example:" msgstr "В этом примере:" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:420 msgid "" "`/usr` resides on `/dev/ada0p3` and its journal provider is `/dev/ada0p5`" msgstr "" "`/usr` находится на `/dev/ada0p3`, а его журнальный провайдер — `/dev/ada0p5`" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:421 msgid "" "`/var` resides on `/dev/ada0p2` and its journal provider is `/dev/ada0p4`" msgstr "" "`/var` находится на `/dev/ada0p2`, а его журнальный провайдер — `/dev/ada0p4`" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:423 msgid "Create the journaled providers using `gjournal(8)`:" msgstr "Создайте журналируемые провайдеры с помощью `gjournal(8)`:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:430 #, no-wrap msgid "" "# gjournal label ada0p3 ada0p5\n" "GEOM_JOURNAL: Journal 2948326772: ada0p5 contains journal.\n" "GEOM_JOURNAL: Journal 2948326772: ada0p3 contains data.\n" "GEOM_JOURNAL: Journal ada0p3 clean.\n" msgstr "" "# gjournal label ada0p3 ada0p5\n" "GEOM_JOURNAL: Journal 2948326772: ada0p5 contains journal.\n" "GEOM_JOURNAL: Journal 2948326772: ada0p3 contains data.\n" "GEOM_JOURNAL: Journal ada0p3 clean.\n" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:435 #, no-wrap msgid "" "# gjournal label ada0p2 ada0p4\n" "GEOM_JOURNAL: Journal 3193218002: ada0p4 contains journal.\n" "GEOM_JOURNAL: Journal 3193218002: ada0p2 contains data.\n" "GEOM_JOURNAL: Journal ada0p2 clean.\n" msgstr "" "# gjournal label ada0p2 ada0p4\n" "GEOM_JOURNAL: Journal 3193218002: ada0p4 contains journal.\n" "GEOM_JOURNAL: Journal 3193218002: ada0p2 contains data.\n" "GEOM_JOURNAL: Journal ada0p2 clean.\n" #. type: delimited block = 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:442 msgid "" "If `gjournal` reports that the last sector of a provider is in use, the " "command will fail. On freshly created or unused partitions, it is safe to " "retry the operation with the `-f` flag to force initialization:" msgstr "" "Если `gjournal` сообщает, что последний сектор провайдера используется, " "команда завершится неудачей. На свежесозданных или неиспользуемых разделах " "безопасно повторить операцию с флагом `-f` для принудительной инициализации:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:446 #, no-wrap msgid "# gjournal label -f /dev/ada0p2 /dev/ada0p4\n" msgstr "# gjournal label -f /dev/ada0p2 /dev/ada0p4\n" #. type: delimited block = 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:450 msgid "After labeling, two new journaled providers are created:" msgstr "После маркировки создаются два новых журналируемых провайдера:" #. type: delimited block = 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:452 msgid "`/dev/ada0p3.journal` for `/usr`" msgstr "`/dev/ada0p3.journal` для `/usr`" #. type: delimited block = 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:453 msgid "`/dev/ada0p2.journal` for `/var`" msgstr "`/dev/ada0p2.journal` для `/var`" #. type: delimited block = 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:455 msgid "" "These devices will replace the original data providers when mounting the " "file systems." msgstr "" "Эти устройства заменят исходные источники данных при монтировании файловых " "систем." #. type: delimited block = 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:457 msgid "" "Before mounting, we must however set the journal flag on them and clear the " "Soft Updates flag:" msgstr "" "Перед монтированием необходимо установить для них флаг журнала и снять флаг " "Soft Updates:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:465 #, no-wrap msgid "" "# tunefs -J enable -n disable -j disable /dev/ada0p3.journal\n" "tunefs: soft updates journaling cleared but soft updates still set\n" "tunefs: remove .sujournal to reclaim space\n" "tunefs: gjournal set\n" "tunefs: soft updates cleared\n" msgstr "" "# tunefs -J enable -n disable -j disable /dev/ada0p3.journal\n" "tunefs: soft updates journaling cleared but soft updates still set\n" "tunefs: remove .sujournal to reclaim space\n" "tunefs: gjournal set\n" "tunefs: soft updates cleared\n" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:471 #, no-wrap msgid "" "# tunefs -J enable -n disable -j disable /dev/ada0p2.journal\n" "tunefs: soft updates journaling cleared but soft updates still set\n" "tunefs: remove .sujournal to reclaim space\n" "tunefs: gjournal set\n" "tunefs: soft updates cleared\n" msgstr "" "# tunefs -J enable -n disable -j disable /dev/ada0p2.journal\n" "tunefs: soft updates journaling cleared but soft updates still set\n" "tunefs: remove .sujournal to reclaim space\n" "tunefs: gjournal set\n" "tunefs: soft updates cleared\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:474 msgid "" "Now, mount the new devices manually at their respective places to verify " "correct operation (note that we can now use the `async` mount option) and " "remove [.filename]#.sujournal# to reclaim space:" msgstr "" "Теперь, смонтируйте новые устройства в соответствующие места файловой " "системы (обратите внимание на то, что мы можем использовать опцию " "монтирования `async`) и удалите [.filename]#.sujournal#, чтобы освободить " "место на диске:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:481 #, no-wrap msgid "" "# mount -o async /dev/ada0p2.journal /var\n" "# rm /var/.sujournal\n" "# mount -o async /dev/ada0p3.journal /usr\n" "# rm /usr/.sujournal\n" msgstr "" "# mount -o async /dev/ada0p2.journal /var\n" "# rm /var/.sujournal\n" "# mount -o async /dev/ada0p3.journal /usr\n" "# rm /usr/.sujournal\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:484 msgid "" "Edit [.filename]#/etc/fstab# and update the entries for [.filename]#/usr# " "and [.filename]#/var#:" msgstr "" "Откройте [.filename]#/etc/fstab# и исправьте записи для следующих файловых " "систем: [.filename]#/usr# и [.filename]#/var#:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:489 #, no-wrap msgid "" "/dev/ada0p3.journal /usr ufs rw,async 2 2\n" "/dev/ada0p2.journal /var ufs rw,async 2 2\n" msgstr "" "/dev/ada0p3.journal /usr ufs rw,async 2 2\n" "/dev/ada0p2.journal /var ufs rw,async 2 2\n" #. type: delimited block = 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:494 msgid "" "Make sure the above entries are correct, or you will have trouble starting " "up normally after you reboot!" msgstr "" "Проверьте корректность всех указанных параметров - в противном случае после " "перезагрузки возможны проблемы со стандартным запуском системы!" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:497 msgid "" "Finally, edit [.filename]#/boot/loader.conf# and add the following line so " "the man:gjournal[8] module is loaded at every boot:" msgstr "" "Наконец, внесите изменения в [.filename]#/boot/loader.conf#, добавив строку " "для автоматической загрузки модуля man:gjournal[8] при каждом старте системы:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:501 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:683 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:817 #, no-wrap msgid "geom_journal_load=\"YES\"\n" msgstr "geom_journal_load=\"YES\"\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:505 msgid "" "Congratulations! Your system is now set for journaling. You can either type " "`exit` to return to multi-user mode, or reboot to test your configuration " "(recommended)." msgstr "" "Поздравляем! Ваша система теперь настроена для журналирования. Вы можете " "ввести команду `exit` для возврата в многопользовательский режим или " "перезагрузить систему для проверки конфигурации (рекомендуется)." #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:509 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:763 #, no-wrap msgid "# shutdown -r now\n" msgstr "# shutdown -r now\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:512 msgid "During the boot you will see messages like the following:" msgstr "Во время перезагрузки вы увидите сообщение следующего вида:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:522 #, no-wrap msgid "" "# dmesg | grep GEOM_JOURNAL\n" "GEOM_JOURNAL: Journal 2948326772: ada0p4 contains journal.\n" "GEOM_JOURNAL: Journal 3193218002: ada0p5 contains journal.\n" "GEOM_JOURNAL: Journal 2948326772: ada0p2 contains data.\n" "GEOM_JOURNAL: Journal ada0p2 clean.\n" "GEOM_JOURNAL: Journal 3193218002: ada0p3 contains data.\n" "GEOM_JOURNAL: Journal ada0p3 clean.\n" msgstr "" "# dmesg | grep GEOM_JOURNAL\n" "GEOM_JOURNAL: Journal 2948326772: ada0p4 contains journal.\n" "GEOM_JOURNAL: Journal 3193218002: ada0p5 contains journal.\n" "GEOM_JOURNAL: Journal 2948326772: ada0p2 contains data.\n" "GEOM_JOURNAL: Journal ada0p2 clean.\n" "GEOM_JOURNAL: Journal 3193218002: ada0p3 contains data.\n" "GEOM_JOURNAL: Journal ada0p3 clean.\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:525 msgid "After an unclean shutdown, the messages will vary slightly, i.e.:" msgstr "" "После некорректного завершения работы сообщения будут немного отличаться, " "например:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:529 #, no-wrap msgid "GEOM_JOURNAL: Journal ada0p2 consistent.\n" msgstr "GEOM_JOURNAL: Journal ada0p2 consistent.\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:532 msgid "" "This usually means that man:gjournal[8] used the information in the journal " "provider to return the file system to a consistent state." msgstr "" "Обычно это означает, что man:gjournal[8] использовал информацию из журнала " "для приведения файловой системы в согласованное состояние." #. type: Title ==== #: documentation/content/en/articles/gjournal-desktop/_index.adoc:534 #, no-wrap msgid "Enabling GEOM Journaling on Newly Created Partitions" msgstr "Включение журналирования GEOM на вновь созданных разделах" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:538 msgid "" "The procedure described earlier is required when enabling GEOM journaling on " "file systems that already contain data. When journaling a newly created, " "empty partition, the process is simpler because both the data and journal " "providers can reside within the same partition." msgstr "" "Процедура, описанная ранее, необходима при включении журналирования GEOM на " "файловых системах, которые уже содержат данные. При журналировании только " "что созданного, пустого раздела процесс проще, так как и данные, и " "журнальные провайдеры могут находиться в одном разделе." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:540 msgid "" "This approach is typically used for new disks or newly allocated partitions " "that have not yet been formatted with a file system." msgstr "" "Такой подход обычно используется для новых дисков или недавно выделенных " "разделов, которые еще не были отформатированы под файловую систему." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:545 msgid "" "While the above procedure is necessary for journaling partitions that " "already contain data, journaling an empty partition is somewhat easier, " "since both the data and the journal provider can be stored in the same " "partition. For example, assume a new disk was installed, and a new " "partition [.filename]#/dev/ada1p1# was created. Creating the journal would " "be as simple as:" msgstr "" "Процедура, описанная выше, необходима для подключения журналирования " "разделов, содержащих данные. Журналирование пустых разделов немного проще, " "ввиду того, что поставщик данных и поставщик журнала могут быть размещены на " "одном и том же разделе. Например, предположим, что был установлен новый " "жёсткий диск и был создан новый раздел [.filename]#/dev/ada1p1#. Создание " "журнала не сложнее набора:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:549 #, no-wrap msgid "# gjournal label /dev/ada1p1\n" msgstr "# gjournal label /dev/ada1p1\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:555 msgid "" "The journal size will be 1 GB by default. You may adjust it by using the `-" "s` option. The value can be given in bytes, or appended by `K`, `M` or `G` " "to denote Kilobytes, Megabytes or Gigabytes respectively. Note that " "`gjournal` will not allow you to create unsuitably small journal sizes." msgstr "" "Размер журнала - 1 Гб по умолчанию. Однако, вы можете изменить это значение " "используя ключ `-s`. Значение можно задавать в байтах, в килобайтах, " "мегабайтах или гигабайтах (используя суффикс `K`, `M` или `G`). Имейте " "ввиду, что команда `gjournal` не позволит вам создать журнал недопустимо " "малого размера." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:557 msgid "" "For example, to create a 2 GB journal, you could use the following command:" msgstr "" "К примеру, чтобы создать журнал размером в 2Гб, можно использовать следующую " "команду:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:561 #, no-wrap msgid "# gjournal label -s 2G /dev/ada1p1\n" msgstr "# gjournal label -s 2G /dev/ada1p1\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:564 msgid "" "You can then initialyze a UFS file system on your new partition, enable " "journaling using `newfs(8)` on the `.journal` device, and disable Soft " "Updates using `tunefs(8)`:" msgstr "" "Далее, вы можете создать файловую систему UFS на новом разделе, разрешить " "журналирование, используя `newfs(8)` на устройстве `.journal`, и запретить " "Soft Updates, используя `tunefs(8)`:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:569 #, no-wrap msgid "" "# newfs -J /dev/ada1p1.journal\n" "# tunefs -n disable -j disable /dev/ada1p1.journal\n" msgstr "" "# newfs -J /dev/ada1p1.journal\n" "# tunefs -n disable -j disable /dev/ada1p1.journal\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:573 msgid "" "After the file system has been created, it can be mounted normally. For " "example, to mount it at `/data`:" msgstr "" "После создания файловой системы её можно смонтировать обычным способом. " "Например, чтобы смонтировать её в `/data`:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:577 #, no-wrap msgid "# mount /dev/ada1p1.journal /data\n" msgstr "# mount /dev/ada1p1.journal /data\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:580 msgid "" "To ensure the file system is mounted automatically at boot, add an entry to " "[.filename]#/etc/fstab#:" msgstr "" "Чтобы обеспечить автоматическое монтирование файловой системы при загрузке, " "добавьте запись в [.filename]#/etc/fstab#:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:584 #, no-wrap msgid "/dev/ada1p1.journal /data ufs rw,async 2 2\n" msgstr "/dev/ada1p1.journal /data ufs rw,async 2 2\n" #. type: Title ===== #: documentation/content/en/articles/gjournal-desktop/_index.adoc:586 #, no-wrap msgid "Notes on Usage" msgstr "Заметки по использованию" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:589 msgid "When using a single provider for both data and journal storage:" msgstr "При использовании одного провайдера для хранения данных и журналов:" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:591 msgid "The partition must be empty before labeling" msgstr "Раздел должен быть пустым перед выполнением `gjournal label`" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:592 msgid "The journal space is allocated from within the partition" msgstr "Журнальное пространство выделяется внутри раздела диска" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:593 msgid "The file system size will be reduced by the size of the journal" msgstr "Размер файловой системы будет уменьшен на размер журнала" #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:595 #, no-wrap msgid "Building Journaling into Your Custom Kernel" msgstr "Встраивание журналирования в собственное ядро" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:599 msgid "" "If you do not wish to load `geom_journal` as a module, you can build its " "functions right into your kernel. Edit your custom kernel configuration " "file, and make sure it includes these two lines:" msgstr "" "Если вы не желаете загружать `geom_journal` как модуль, то можно встроить " "его функции прямо в ваше специализированное ядро. Редактируя " "конфигурационный файл ядра, убедитесь, что в нём находятся следующие две " "строки:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:603 #, no-wrap msgid "options UFS_GJOURNAL <1>\n" msgstr "options UFS_GJOURNAL <1>\n" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:605 #, no-wrap msgid "options GEOM_JOURNAL <2>\n" msgstr "options GEOM_JOURNAL <2>\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:608 msgid "Note: This is already in GENERIC" msgstr "Обратите внимание — это уже есть в GENERIC" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:609 msgid "You will have to add this one" msgstr "Вам надо добавить эту опцию" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:612 msgid "" "Rebuild and reinstall your kernel following the relevant extref:{handbook}" "kernelconfig[instructions in the FreeBSD Handbook., kernelconfig]" msgstr "" "Соберите и установите новое ядро следуя указаниям extref:{handbook}" "kernelconfig[Руководства FreeBSD., kernelconfig]" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:614 msgid "" "Do not forget to remove the relevant \"load\" entry from [.filename]#/boot/" "loader.conf# if you have previously used it." msgstr "" "И не забудьте удалить соответствующую строку загрузки модуля (\"load\") из [." "filename]#/boot/loader.conf# (если на предыдущем этапе она была туда " "внесена)." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:615 #, no-wrap msgid "Checking GEOM Journaling" msgstr "Проверка GEOM журналирования" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:618 msgid "" "GEOM journaling status can be verified by inspecting active GEOM providers." msgstr "" "Статус журналирования GEOM можно уточнить, проверив активные провайдеры GEOM." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:620 msgid "To list all active GEOM journal devices, run:" msgstr "" "Чтобы вывести список всех активных устройств журналирования GEOM, выполните:" #. type: delimited block - 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:624 #, no-wrap msgid "# gjournal list\n" msgstr "# gjournal list\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:627 msgid "Or to view a summary of journal status:" msgstr "Или для просмотра сводки состояния журнала:" #. type: delimited block - 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:631 #, no-wrap msgid "# gjournal status\n" msgstr "# gjournal status\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:635 msgid "" "Journaled file systems are identified by device names ending in `.journal`. " "The presence of these providers indicates that GEOM journaling is active." msgstr "" "Журналируемые файловые системы обозначаются именами устройств, " "оканчивающимися на `.journal`. Наличие этих провайдеров указывает на " "активность журналирования GEOM." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:637 msgid "Additional information about GEOM device stacking can be obtained with:" msgstr "" "Дополнительную информацию о цепочке устройств GEOM можно получить с помощью:" #. type: delimited block - 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:641 #, no-wrap msgid "# geom -t\n" msgstr "# geom -t\n" #. type: delimited block - 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:649 #, no-wrap msgid "" "# dumpfs /dev/ada0p2.journal | grep -i journal\n" "flags gjournal\n" msgstr "" "# dumpfs /dev/ada0p2.journal | grep -i journal\n" "flags gjournal\n" #. type: Title == #: documentation/content/en/articles/gjournal-desktop/_index.adoc:653 #, no-wrap msgid "Troubleshooting Journaling" msgstr "Устранение неполадок с журналированием" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:656 msgid "" "The following section covers frequently asked questions regarding problems " "related to journaling." msgstr "" "Этот раздел содержит часто задаваемые вопросы касательно неполадок, " "связанных с журналированием." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:657 #, no-wrap msgid "I am experiencing kernel panics during periods of high disk activity. Is this related to GEOM journaling?" msgstr "" "Я получаю паники ядра во время высокой дисковой активности. Это связано с " "журналированием GEOM?" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:660 msgid "" "On modern FreeBSD systems, kernel panics caused solely by an undersized GEOM " "journal are rare." msgstr "" "На современных системах FreeBSD аварийные остановки системы, вызванные " "исключительно недостаточным размером журнала GEOM, встречаются редко." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:663 msgid "" "Under sustained or burst-heavy write workloads, an undersized journal " "typically results in write throttling or temporary I/O stalls while the " "journal is flushed to the data provider. A kernel panic may occur only in " "exceptional cases, usually in combination with additional problems such as I/" "O errors or resource exhaustion, where continuing operation could risk file " "system integrity." msgstr "" "При продолжительных или интенсивных всплесках нагрузки на запись, " "недостаточный размер журнала обычно приводит к регулированию записи или " "временным задержкам ввода-вывода во время сброса журнала на устройство " "хранения данных. Аварийная остановка системы может возникнуть лишь в " "исключительных случаях, обычно в сочетании с дополнительными проблемами, " "такими как ошибки ввода-вывода или исчерпание ресурсов, когда продолжение " "работы может угрожать целостности файловой системы." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:665 msgid "" "If panics are observed during heavy write activity, increasing the size of " "the journal provider for the affected file system is recommended." msgstr "" "Если наблюдаются аварийные остановки при интенсивной активности записи, " "рекомендуется увеличить размер журнала для затронутой файловой системы." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:666 #, no-wrap msgid "I made some mistake during configuration, and I cannot boot normally now. Can this be fixed some way?" msgstr "Я допустил некоторые ошибки во время конфигурирования, теперь система не загружается. Можно это как-нибудь исправить?" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:672 msgid "" "You either forgot (or misspelled) the entry in [.filename]#/boot/loader." "conf#, or there are errors in your [.filename]#/etc/fstab# file. These are " "usually easy to fix. During system startup, when the boot process stops and " "prompts for single-user mode (for example after a failed mount or `fsck` " "error), press kbd:[Enter] to get to the default single user shell. Then " "locate the root of the problem:" msgstr "" "Вы либо забыли внести запись (опечатались) в [.filename]#/boot/loader.conf#, " "либо есть ошибки в файле [.filename]#/etc/fstab#. Это легко исправить. Во " "время загрузки системы, когда процесс загрузки остановится и появится запрос " "входа в однопользовательский режим (например, после сбоя монтирования или " "ошибки `fsck`), нажмите kbd:[Enter], чтобы получить приглашение командного " "интерпретатора в однопользовательском режиме. Потом, проверьте возможные " "варианты:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:676 #, no-wrap msgid "# cat /boot/loader.conf\n" msgstr "# cat /boot/loader.conf\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:679 msgid "Ensure that the following line exists and is spelled correctly:" msgstr "Убедитесь, что следующая строка существует и написана правильно:" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:687 msgid "" "If the `geom_journal_load` entry is missing or misspelled, the journaled " "devices are never created. Load the module manually, mount all partitions, " "and continue with multi-user boot:" msgstr "" "Если отсутствует запись `geom_journal_load`, или она содержит ошибки, " "журналируемые устройства не создадутся. Загрузите модуль вручную, " "примонтируйте все разделы и переходите в многопользовательский режим " "(продолжайте загрузку):" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:698 #, no-wrap msgid "" "GEOM_JOURNAL: Journal 2948326772: ada0p4 contains journal.\n" "GEOM_JOURNAL: Journal 3193218002: ada0p5 contains journal.\n" "GEOM_JOURNAL: Journal 2948326772: ada0p2 contains data.\n" "GEOM_JOURNAL: Journal ada0p2 clean.\n" "GEOM_JOURNAL: Journal 3193218002: ada0p3 contains data.\n" "GEOM_JOURNAL: Journal ada0p3 clean.\n" msgstr "" "GEOM_JOURNAL: Journal 2948326772: ada0p4 contains journal.\n" "GEOM_JOURNAL: Journal 3193218002: ada0p5 contains journal.\n" "GEOM_JOURNAL: Journal 2948326772: ada0p2 contains data.\n" "GEOM_JOURNAL: Journal ada0p2 clean.\n" "GEOM_JOURNAL: Journal 3193218002: ada0p3 contains data.\n" "GEOM_JOURNAL: Journal ada0p3 clean.\n" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:702 #, no-wrap msgid "" "# mount -a\n" "# exit\n" "(boot continues)\n" msgstr "" "# mount -a\n" "# exit\n" "(boot continues)\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:707 msgid "" "If, on the other hand, this entry is correct, have a look at [.filename]#/" "etc/fstab#. You will probably find a misspelled or missing entry. In this " "case, mount all remaining partitions by hand and continue with the multi-" "user boot." msgstr "" "Если же запись о `geom_journal_load` верна, то проверьте [.filename]#/etc/" "fstab#. Вероятней всего, что вы обнаружите опечатку или отсутствие " "необходимой записи. В этом случае смонтируйте вручную оставшиеся разделы и " "продолжите загрузку в многопользовательский режим." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:708 #, no-wrap msgid "Can I remove journaling and return to my standard file system with Soft Updates?" msgstr "Возможно ли отказаться от журналирования и вернуться к моей привычной файловой системе с механизмом Soft Updates?" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:713 msgid "" "Sure. Use the following procedure, which reverses the changes. The " "partitions you created for the journal providers can then be used for other " "purposes, if you so wish." msgstr "" "Несомненно. Используйте приведённую ниже последовательность действий, " "которая обращает изменения. Разделы, созданные для поставщиков журналов, " "могут позже быть использованы для других целей." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:715 msgid "Login as `root` and switch to single user mode:" msgstr "Залогиньтесь `root` и переведите систему в однопользовательский режим:" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:722 msgid "Unmount the journaled partitions:" msgstr "Размонтируйте журналируемые разделы:" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:729 msgid "Synchronize the journals:" msgstr "Синхронизируйте журналы:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:733 #, no-wrap msgid "# gjournal sync\n" msgstr "# gjournal sync\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:736 msgid "Stop the journaling providers:" msgstr "Остановите поставщиков журналов:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:741 #, no-wrap msgid "" "# gjournal stop ada0p2.journal\n" "# gjournal stop ada0p3.journal\n" msgstr "" "# gjournal stop ada0p2.journal\n" "# gjournal stop ada0p3.journal\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:745 msgid "" "Next step should be done with unloaded gjournal kernel module. If the " "following command fails:" msgstr "" "Следующий шаг должен быть выполнен с выгруженным модулем ядра gjournal. Если " "следующая команда завершится неудачей:" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:750 msgid "... # gjournal unload ..." msgstr "... # gjournal unload ..." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:752 msgid "" "ensure that the following line exists in [.filename]#/boot/loader.conf# and " "is spelled correctly:" msgstr "" "Убедитесь, что следующая строка присутствует в [.filename]#/boot/loader.conf#" " и написана правильно:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:756 #, no-wrap msgid "geom_journal_load=\"NO\"\n" msgstr "geom_journal_load=\"NO\"\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:759 msgid "Reboot your desktop without gjournal kernel module:" msgstr "Перезагрузите ваш компьютер без модуля ядра gjournal:" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:766 msgid "" "Boot into single-user mode again. Clear the journaling metadata from all the " "devices used:" msgstr "" "Войдите в систему в однопользовательском режиме еще раз. Удалите метаданные " "журналирования со всех задействованных устройств:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:773 #, no-wrap msgid "" "# gjournal clear ada0p2\n" "# gjournal clear ada0p3\n" "# gjournal clear ada0p4\n" "# gjournal clear ada0p5\n" msgstr "" "# gjournal clear ada0p2\n" "# gjournal clear ada0p3\n" "# gjournal clear ada0p4\n" "# gjournal clear ada0p5\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:776 msgid "" "Clear the file system journaling flag, and restore the Soft Updates flags:" msgstr "Снимите флаг журналирования и установите флаги механизма Soft Updates:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:783 #, no-wrap msgid "" "# tunefs -J disable -n enable -j enable ada0p2\n" "tunefs: soft updates journaling set\n" "tunefs: gjournal cleared\n" "tunefs: soft updates set\n" msgstr "" "# tunefs -J disable -n enable -j enable ada0p2\n" "tunefs: soft updates journaling set\n" "tunefs: gjournal cleared\n" "tunefs: soft updates set\n" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:788 #, no-wrap msgid "" "# tunefs -J disable -n enable -j enable ada0p3\n" "tunefs: soft updates journaling set\n" "tunefs: gjournal cleared\n" "tunefs: soft updates set\n" msgstr "" "# tunefs -J disable -n enable -j enable ada0p3\n" "tunefs: soft updates journaling set\n" "tunefs: gjournal cleared\n" "tunefs: soft updates set\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:791 msgid "Remount the old devices by hand:" msgstr "Смонтируйте вручную старые (первоначальные) устройства:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:796 #, no-wrap msgid "" "# mount -o rw /dev/ada0p2 /var\n" "# mount -o rw /dev/ada0p3 /usr\n" msgstr "" "# mount -o rw /dev/ada0p2 /var\n" "# mount -o rw /dev/ada0p3 /usr\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:799 msgid "Edit [.filename]#/etc/fstab# and restore it to its original state:" msgstr "" "Откройте файл [.filename]#/etc/fstab# и приведите его к изначальному виду:" #. type: delimited block . 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:804 #, no-wrap msgid "" "/dev/ada0p2 /usr ufs rw 2 2\n" "/dev/ada0p3 /var ufs rw 2 2\n" msgstr "" "/dev/ada0p2 /usr ufs rw 2 2\n" "/dev/ada0p3 /var ufs rw 2 2\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:807 msgid "" "Finally, edit [.filename]#/boot/loader.conf#, remove the entry that loads " "the `geom_journal` module (or re-enable it if gjournal is still required for " "other partitions), and reboot." msgstr "" "И напоследок, удалите строку, загружающую модуль `geom_journal`, из файла [." "filename]#/boot/loader.conf# (или включите его опять, если он по прежнему " "требуется для других разделов диска), и перезагрузите операционную систему." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:808 #, no-wrap msgid "How do I temporarily boot without GEOM journaling?" msgstr "Как временно загрузиться без журналирования GEOM?" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:811 msgid "" "To boot the system without GEOM journaling, prevent the journal module from " "loading during startup." msgstr "" "Чтобы загрузить систему без журналирования GEOM, предотвратите загрузку " "модуля журнала во время запуска." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:813 msgid "" "Comment out or remove the following line from [.filename]#/boot/loader.conf# " "and reboot:" msgstr "" "Закомментируйте или удалите соответствующую строку из [.filename]#/boot/" "loader.conf# и перезагрузитесь:" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:821 msgid "" "After booting without GEOM journaling, journaled devices (`*.journal`) will " "not be created. File Systems must be mounted using their original (non-" "journaled) providers, or mounted manually as needed for recovery or " "maintenance." msgstr "" "После загрузки без журналирования GEOM, журналируемые устройства (`*." "journal`) не будут созданы. Файловые системы должны быть смонтированы с " "использованием их исходных (не журналируемых) провайдеров или вручную по " "мере необходимости для восстановления или обслуживания." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:823 msgid "" "This method does not modify on-disk journal metadata and can be safely used " "for troubleshooting." msgstr "" "Этот метод не изменяет метаданные журнала на диске и может безопасно " "использоваться для устранения неполадок." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:824 #, no-wrap msgid "Can I resize a GEOM journal after it has been created?" msgstr "Можно ли изменить размер журнала GEOM после его создания?" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:827 msgid "" "No. A GEOM journal cannot be resized in place after it has been created." msgstr "" -"Нет. Журнал GEOM не может быть изменен в размере на месте после его создания." +"Нет. Журнал GEOM не может быть изменён в размере на месте после его создания." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:831 msgid "" "The journal size is fixed at the time the journal is labeled. To change the " "journal size, GEOM journaling must be removed and reconfigured with a new " "journal provider of the desired size. For file systems containing data, " "this requires unmounting the file system and recreating the journal using " "appropriately sized providers, as described earlier in this article." msgstr "" "Размер журнала фиксируется в момент выполнения `gjournal label` . Чтобы " "изменить размер журнала, необходимо удалить журналирование GEOM и " "переконфигурировать его с новым провайдером журнала желаемого размера. Для " "файловых систем, содержащих данные, это требует размонтирования файловой " "системы и воссоздания журнала с использованием провайдеров соответствующего " "размера, как описано ранее в этой статье." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:833 msgid "" "Plan journal sizes conservatively to accommodate peak write activity, as " "resizing requires reinitialization of the journal configuration." msgstr "" "Планируйте размеры журналов консервативно, чтобы они соответствовали пиковой " "активности записи, так как изменение размера требует повторной инициализации " "конфигурации журнала." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:834 #, no-wrap msgid "What happens after an unclean shutdown or power failure?" msgstr "Что происходит после некорректного завершения работы или сбоя питания?" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:837 msgid "" "After an unclean shutdown or power failure, GEOM journaling and Soft Updates " "with journaling replay the pending journal records during the next boot to " "return the file system to a consistent state." msgstr "" "После некорректного завершения работы или сбоя питания, журналирование GEOM " "и Soft Updates с журналированием воспроизводят ожидающие записи журнала во " "время следующей загрузки, чтобы вернуть файловую систему в согласованное " "состояние." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:840 msgid "" "If the journal replay completes successfully, the file system is mounted " "normally and no full file system check is required. Journal replay " "typically takes only a few seconds and depends on the amount of recent write " "activity rather than the size of the file system." msgstr "" "Если восстановление журнала завершается успешно, файловая система " "монтируется в обычном режиме, и полная проверка файловой системы не " "требуется. Восстановление журнала обычно занимает всего несколько секунд и " "зависит от объема недавней активности записи, а не от размера файловой " "системы." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:842 msgid "" "A full file system check may still be required in rare cases, such as when " "underlying storage errors are detected or the journal itself is inconsistent." msgstr "" "Полная проверка файловой системы может потребоваться в редких случаях, " "например, при обнаружении ошибок в устройстве хранения или несоответствии " "самого журнала." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:843 #, no-wrap msgid "How does GEOM journaling interact with fsck?" msgstr "Как взаимодействует журналирование GEOM с fsck?" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:846 msgid "" "GEOM journaling and Soft Updates with journaling interact with `fsck_ffs(8)` " "in different ways, reflecting their different integration levels in the " "FreeBSD storage stack." msgstr "" "Журналирование GEOM и Soft Updates с журналированием взаимодействуют с " "`fsck_ffs(8)` различными способами, отражая их разные уровни интеграции в " "стеке хранения FreeBSD." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:851 msgid "" "For GEOM journaling, crash recovery is performed by the GEOM framework " "itself. During system startup, the `geom_journal` class detects journal " "metadata and replays any pending journal records while the provider is being " "tasted by GEOM, before the journaled device becomes visible to higher layers " "of the system. If journal replay completes successfully, the file system is " "returned to a consistent state and the UFS superblock is updated to indicate " "that no file system check is required. When `fsck_ffs(8)` is later invoked " "during boot, it reads this state from the superblock and skips the file " "system check." msgstr "" "Для журналирования GEOM восстановление после сбоя выполняется самой " "структурой GEOM. Во время запуска системы класс `geom_journal` обнаруживает " "метаданные журнала и воспроизводит все ожидающие записи журнала, пока " "провайдер обрабатывается GEOM, до того как журналируемое устройство станет " "видимым для более высоких уровней системы. Если воспроизведение журнала " "завершается успешно, файловая система возвращается в согласованное " "состояние, и суперблок UFS обновляется, чтобы указать, что проверка файловой " "системы не требуется. Когда позже во время загрузки вызывается `fsck_ffs(8)`" ", он считывает это состояние из суперблока и пропускает проверку файловой " "системы." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:856 msgid "" "For Soft Updates with journaling, recovery is initiated by `fsck_ffs(8)` " "itself. During the file system check phase at boot time, `fsck_ffs(8)` " "detects that the files ystem supports Soft Updates with journaling and " "invokes the journal replay logic. If journal replay reports that the file " "system is consistent, `fsck_ffs(8)` terminates early without performing a " "full check. If journal replay cannot complete successfully, a traditional " "file system check is performed." msgstr "" "Для Soft Updates с журналированием восстановление инициируется самим " "`fsck_ffs(8)`. Во время проверки файловой системы при загрузке, `fsck_ffs(8)`" " обнаруживает, что файловая система поддерживает Soft Updates с " "журналированием, и запускает логику воспроизведения журнала. Если " "воспроизведение журнала сообщает, что файловая система непротиворечива, " "`fsck_ffs(8)` завершается досрочно без выполнения полной проверки. Если " "воспроизведение журнала не может быть успешно завершено, выполняется " "традиционная проверка файловой системы." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:858 msgid "" "As a result, the recovery path during system startup depends on the " "journaling mechanism in use, as illustrated by the following boot sequence:" msgstr "" "В результате, путь восстановления во время загрузки системы зависит от " "используемого механизма журналирования, что иллюстрируется следующей " "последовательностью загрузки:" #. type: delimited block - 4 #: documentation/content/en/articles/gjournal-desktop/_index.adoc:885 #, no-wrap msgid "" "Firmware / Boot Loader\n" " |\n" " v\n" "Kernel initialization\n" " |\n" " v\n" "GEOM framework (provider tasting)\n" " |\n" " +--> GEOM journaling (gjournal)\n" " | - Journal replay occurs here\n" " | - Filesystem consistency is restored\n" " | - Superblock is updated\n" " |\n" " v\n" "Filesystem check phase (fsck_ffs)\n" " |\n" " +--> Soft Updates with journaling\n" " | - Journal replay initiated by fsck\n" " | - fsck exits early if consistent\n" " |\n" " v\n" "Filesystem mount\n" " |\n" " v\n" "Normal system operation\n" msgstr "" "Загрузчик системы\n" " |\n" " v\n" "Инициализация ядра\n" " |\n" " v\n" "Фреймворк GEOM framework (обнаружение поставщиков - tasting)\n" " |\n" " +--> Журналирование GEOM (gjournal)\n" " | - Выполнение записи на диск из журнала выполняется на этом " "этапе\n" " | - Согласованность файловой системы восстановлена\n" " | - Суперблок обновлен\n" " |\n" " v\n" "Фаза проверки файловой системы (fsck_ffs)\n" " |\n" " +--> Журналирование с Soft Updates\n" " | - Выполнение записи на диск из журнала, инициированное " "командой fsck\n" " | - fsck сразу выходит, если файловая система в согласованном " "состоянии\n" " |\n" " v\n" "Монтирование файловой системы\n" " |\n" " v\n" "Обычная работа системы\n" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:889 msgid "" "`fsck_ffs(8)` is still used when journal replay cannot be completed, when " "underlying storage errors are detected, or during periodic manual or " "scheduled file system checks. GEOM journaling reduces recovery time after " "crashes but does not replace `fsck_ffs(8)` entirely." msgstr "" "`fsck_ffs(8)` всё ещё используется, когда восстановление журнала не может " "быть завершено, при обнаружении ошибок базового хранилища или во время " "периодических ручных или запланированных проверок файловой системы. " "Журналирование GEOM сокращает время восстановления после сбоев, но не " "заменяет `fsck_ffs(8)` полностью." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:890 #, no-wrap msgid "Why does `gjournal clear` report \"Operation not permitted\" even in single-user mode?" msgstr "" "Почему команда `gjournal clear` сообщает \"Операция не разрешена\" даже в " "однопользовательском режиме?" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:895 msgid "" "In GEOM, the same underlying storage can be exposed through multiple " "provider names at the same time. For example, a partition may be visible " "both under its disk-based name (e.g. `vtbd0p7`) and under a GPT label (e.g. " "`/dev/gpt/labelname`). These are different GEOM providers referring to the " "same physical storage." msgstr "" "В GEOM одно и то же базовое хранилище может быть представлено через " "несколько имён провайдеров одновременно. Например, раздел может быть виден " "как под своим именем, основанным на диске (например, `vtbd0p7`), так и под " "меткой GPT (например, `/dev/gpt/labelname`). Это разные провайдеры GEOM, " "ссылающиеся на одно и то же физическое хранилище." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:898 msgid "" "When `gjournal stop` or `gjournal clear` is executed on one provider name, " "the GEOM framework may immediately detect the journal metadata again through " "another provider name during the tasting process. As a result, the journal " "is re-attached automatically, and attempts to clear its metadata fail with " "an \"Operation not permitted\" error." msgstr "" "Когда команды `gjournal stop` или `gjournal clear` выполняются на одном " "имени провайдера, фреймворк GEOM может немедленно снова обнаружить " "метаданные журнала через другое имя провайдера в процессе распознавание " "устройства (tasting). В результате журнал автоматически повторно " "присоединяется, и попытки очистить его метаданные завершаются ошибкой " "\"Операция не разрешена\"." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:901 msgid "" "It is technically possible to suppress this behavior by disabling GEOM " "tasting or by preventing the creation of alternative provider names, but " "doing so is strongly discouraged. Such changes may negatively affect other " "GEOM classes and system components that rely on normal provider discovery." msgstr "" "Технически возможно подавить это поведение, отключив GEOM tasting или " "предотвратив создание альтернативных имён провайдеров, однако это крайне не " "рекомендуется. Такие изменения могут негативно повлиять на другие классы " "GEOM и системные компоненты, которые полагаются на обычное обнаружение " "провайдеров." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:904 msgid "" "For this reason, the recommended and safe procedure is to unload the " "`geom_journal` module entirely before removing journal metadata, as " "described earlier in this article. With the module unloaded, no tasting " "occurs and the journal cannot be re-attached, allowing `gjournal clear` to " "complete successfully." msgstr "" "По этой причине рекомендованная и безопасная процедура заключается в полной " "выгрузке модуля `geom_journal` перед удалением журнальных метаданных, как " "описано ранее в этой статье. При выгруженном модуле не происходит " "автоматического распознавания, и журнал не может быть повторно подключен, " "что позволяет команде `gjournal clear` завершиться успешно." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:905 #, no-wrap msgid "Can GEOM journaling be used on the root file system?" msgstr "Можно ли использовать журналирование GEOM на корневой файловой системе?" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:908 msgid "" "Yes. GEOM journaling can be used on the root file system, but it requires " "additional care during system configuration." msgstr "" "Да. Журналирование GEOM может использоваться на корневой файловой системе, " "но требует дополнительной осторожности при настройке системы." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:911 msgid "" "The GEOM journal module must be loaded early during the boot process so that " "the journaled root device is available before the root file system is " "mounted. Misconfiguration may prevent the system from booting normally, so " "this setup is generally recommended only for experienced users who fully " "understand the boot sequence and recovery procedures." msgstr "" "Модуль GEOM journal должен быть загружен на раннем этапе процесса загрузки, " "чтобы журналируемое корневое устройство было доступно до монтирования " "корневой файловой системы. Неправильная конфигурация может помешать системе " "загрузиться в обычном режиме, поэтому данная настройка, как правило, " "рекомендуется только опытным пользователям, которые полностью понимают " "последовательность загрузки и процедуры восстановления." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:913 msgid "" "For these reasons, GEOM journaling is more commonly applied to non-root file " "systems such as `/usr` and `/var`." msgstr "" "По этим причинам журналирование GEOM чаще применяется к некорневым файловым " "системам, таким как `/usr` и `/var`." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:914 #, no-wrap msgid "What are the performance implications of using GEOM journaling?" msgstr "" "Каковы последствия для производительности при использовании журналирования " "GEOM?" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:918 msgid "" "GEOM journaling introduces additional write I/O because all write operations " "are first recorded in the journal before being committed to the data " "provider. This results in increased write latency and higher overall write " "amplification compared to non-journaled file systems." msgstr "" "Ведение журнала GEOM вводит дополнительные операции записи ввода-вывода, " "поскольку все операции записи сначала регистрируются в журнале перед " "фиксацией на устройстве хранения данных. Это приводит к увеличению задержки " "записи и более высокому коэффициенту увеличения объёма записи по сравнению с " "файловыми системами без журналирования." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:922 msgid "" "Read performance is typically unaffected. The performance impact is most " "noticeable on write-heavy workloads and depends on journal size, placement, " "and the speed of the underlying storage. Using a sufficiently sized journal " "and fast storage for the journal provider minimizes performance penalties." msgstr "" "Производительность чтения обычно не страдает. Наиболее заметное влияние на " "производительность наблюдается при интенсивных нагрузках на запись и зависит " "от размера журнала, его размещения и скорости базового хранилища. " "Использование журнала достаточного размера и быстрого хранилища для " "поставщика журнала минимизирует потери в производительности." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:923 #, no-wrap msgid "Can GEOM journaling be used together with other GEOM classes?" msgstr "" "Может ли журналирование GEOM использоваться вместе с другими классами GEOM?" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:926 msgid "Yes. GEOM journaling can be stacked with other GEOM classes." msgstr "Да. GEOM журналирование может быть объединено с другими классами GEOM." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:929 msgid "" "When used together, GEOM journaling typically operates on top of providers " "created by other GEOM classes such as `gmirror(8)` or `graid3(8)`. The " "order of stacking is important and should follow the documented layering " "requirements of the involved GEOM classes." msgstr "" "При совместном использовании журналирование GEOM обычно работает поверх " "провайдеров, созданных другими классами GEOM, такими как `gmirror(8)` или " "`graid3(8)`. Порядок наложения важен и должен соответствовать " "задокументированным требованиям к слоям задействованных классов GEOM." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:931 msgid "" "GEOM journaling maintains file system consistency across the stacked " "providers, but it does not replace redundancy or error detection provided by " "other GEOM classes." msgstr "" "GEOM журналирование обеспечивает целостность файловой системы на всех " "уровнях поставщиков, но не заменяет избыточность или обнаружение ошибок, " "предоставляемые другими классами GEOM." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:932 #, no-wrap msgid "Can GEOM journaling and Soft Updates be enabled at the same time?" msgstr "Можно ли одновременно включить журналирование GEOM и Soft Updates?" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:935 msgid "" "No. GEOM journaling and Soft Updates must not be enabled at the same time on " "the same file system." msgstr "" "Нет. GEOM журналирование и Soft Updates не должны быть включены одновременно " "на одной файловой системе." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:938 msgid "" "GEOM journaling requires exclusive control over write ordering and " "consistency guarantees. If Soft Updates are enabled together with GEOM " "journaling, the file system may behave unpredictably and data integrity " "cannot be guaranteed." msgstr "" "GEOM журналирование требует исключительного контроля над порядком записи и " "гарантиями согласованности. Если Soft Updates включены вместе с GEOM " "журналированием, файловая система может вести себя непредсказуемо, и " "целостность данных не может быть гарантирована." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:940 msgid "" "When using GEOM journaling, Soft Updates must be disabled on the affected " "file system, as described earlier in this article." msgstr "" "При использовании журналирования GEOM необходимо отключить Soft Updates на " "затронутой файловой системе, как описано ранее в этой статье." #. type: Title === #: documentation/content/en/articles/gjournal-desktop/_index.adoc:942 #, no-wrap msgid "What is the difference between Soft Updates and Soft Updates with Journaling?" msgstr "В чем разница между Soft Updates и Soft Updates с журналированием?" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:945 msgid "" "Both Soft Updates and Soft Updates with Journaling are designed to maintain " "file system consistency, but they use different mechanisms and behave " "differently after a system crash." msgstr "" "Как Soft Updates, так и Soft Updates with Journaling предназначены для " "поддержания целостности файловой системы, но используют разные механизмы и " "ведут себя по-разному после сбоя системы." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:949 msgid "" "_Soft Updates_ ensure consistency by carefully ordering metadata writes in " "memory so that only safe states are written to disk. If a crash occurs, any " "metadata updates that have not yet been written are simply lost, leaving the " "file system in a consistent but possibly older state. However, resource " "accounting may be temporarily inaccurate, and a full `fsck_ffs(8)` run is " "required to reclaim unused blocks and inodes." msgstr "" "_Soft Updates_ обеспечивают целостность за счёт тщательного упорядочивания " "записи метаданных в памяти, так что на диск записываются только безопасные " "состояния. При сбое любые обновления метаданных, ещё не записанные на диск, " "просто теряются, оставляя файловую систему в целостном, но, возможно, более " "старом состоянии. Однако учёт ресурсов может временно быть неточным, и для " "освобождения неиспользуемых блоков и индексных дескрипторов требуется полный " "запуск `fsck_ffs(8)`." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:953 msgid "" "_Soft Updates with Journaling_ build on top of _Soft Updates_ by adding a " "metadata journal stored within the file system. Metadata changes are first " "recorded in the journal and are replayed automatically during the next boot " "after an unclean shutdown. This allows the file system to be restored to a " "consistent state quickly, usually without requiring a full `fsck_ffs(8)` run." msgstr "" "_Soft Updates с журналированием_ расширяют функциональность _Soft Updates _, " "добавляя журнал метаданных, хранящийся в файловой системе. Изменения " "метаданных сначала записываются в журнал и автоматически воспроизводятся при " "следующей загрузке после некорректного завершения работы. Это позволяет " "быстро восстановить файловую систему в согласованное состояние, обычно без " "необходимости полного запуска `fsck_ffs(8)`." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:955 msgid "" "In short, _Soft Updates_ provide consistency without a journal, while _Soft " "Updates with Journaling_ add fast and automatic recovery after crashes at " "the cost of additional disk space and minor performance overhead." msgstr "" "Короче говоря, _Soft Updates_ обеспечивают согласованность без " "журналирования, тогда как _Soft Updates с журналированием_ добавляют быстрое " "и автоматическое восстановление после сбоев ценой дополнительного дискового " "пространства и незначительного снижения производительности." #. type: Title == #: documentation/content/en/articles/gjournal-desktop/_index.adoc:958 #, no-wrap msgid "Further Reading" msgstr "Для дальнейшего ознакомления" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:962 msgid "" "Journaling is a fairly new feature of FreeBSD, and as such, it is not very " "well documented yet. You may however find the following additional " "references useful:" msgstr "" "Журналирование - относительно новая функциональная возможность FreeBSD, и " "она ещё недостаточно документирована. Однако, могут быть полезными следующие " "источники:" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:964 msgid "" "A extref:{handbook}geom[section on journaling, geom-gjournal] is now part of " "the FreeBSD Handbook." msgstr "" "extref:{handbook}geom[Раздел Руководства FreeBSD, geom-gjournal], " "посвященный журналированию." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:965 msgid "" "https://lists.freebsd.org/pipermail/freebsd-current/2006-June/064043." "html[This post] in {freebsd-current} by man:gjournal[8]'s developer, `{pjd}`." msgstr "" "http://lists.freebsd.org/pipermail/freebsd-current/2006-June/064043." "html[Этот пост] в списке рассылки {freebsd-current}, написанный `{pjd}` - " "автором man:gjournal[8]." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:966 msgid "" "https://lists.freebsd.org/pipermail/freebsd-questions/2008-April/173501." "html[This post] in {freebsd-questions} by `{ivoras}`." msgstr "" "http://lists.freebsd.org/pipermail/freebsd-questions/2008-April/173501." "html[Этот пост] от `{ivoras}` в списке рассылки {freebsd-questions}." #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:967 msgid "" "https://www.youtube.com/watch?v=_NuhRkiInvA[Journaled Soft-Updates, Dr. Kirk " "McKusick, BSDCan 2010] on YouTube" msgstr "" "https://www.youtube.com/watch?v=_NuhRkiInvA[Journaled Soft-Updates, Dr. Kirk " "McKusick, BSDCan 2010] на YouTube" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:968 msgid "" "https://www.youtube.com/watch?v=xMpmOezBJZo[GEOM - in Infrastructure We " "Trust, Pawel Jakub Dawidek, AsiaBSDCon 2008] on YouTube" msgstr "" "https://www.youtube.com/watch?v=xMpmOezBJZo[GEOM - in Infrastructure We " "Trust, Pawel Jakub Dawidek, AsiaBSDCon 2008] на YouTube" #. type: Plain text #: documentation/content/en/articles/gjournal-desktop/_index.adoc:968 msgid "The manual pages of man:gjournal[8], man:geom[8], and man:tunefs[8]." msgstr "Страницы Справочника man:gjournal[8], man:geom[8] и man:tunefs[8]." #~ msgid "" #~ "The new journaling capability provided by GEOM can greatly assist in such " #~ "scenarios, by virtually eliminating the time required for file system " #~ "checking, and ensuring that the file system is quickly restored to a " #~ "consistent state." #~ msgstr "" #~ "Новая возможность журналирования, предоставленная системой GEOM, может " #~ "существенно выручить в подобных случаях, исключая время, необходимое для " #~ "проверки файловых систем и удостовериваясь, что файловая система быстро " #~ "восстановлена в целостное состояние." #~ msgid "" #~ "This article describes a procedure for implementing UFS journaling on a " #~ "typical desktop PC scenario (one hard disk used for both operating system " #~ "and data). It should be followed during a fresh installation of " #~ "FreeBSD. The steps are simple enough and do not require overly complex " #~ "interaction with the command line." #~ msgstr "" #~ "Эта статья описывает порядок действий, необходимых для конфигурирования " #~ "журналирования UFS на типичном настольном компьютере, в котором один " #~ "жёсткий диск используется для размещения как операционной системы, так и " #~ "данных. В статье подразумевается установка FreeBSD \"с нуля\". Шаги " #~ "достаточно просты и не требуют чрезмерно сложных манипуляций с командной " #~ "строкой." #~ msgid "After reading this article, you will know:" #~ msgstr "После прочтения данной статьи вы будете знать:" #~ msgid "" #~ "How to reserve space for journaling during a new installation of FreeBSD." #~ msgstr "" #~ "Как зарезервировать место для журнала во время новой установки FreeBSD." #~ msgid "" #~ "How to load and enable the `geom_journal` module (or build support for it " #~ "in your custom kernel)." #~ msgstr "" #~ "Как загрузить модуль `geom_journal` (или включить поддержку " #~ "журналирования в специализированном ядре системы)." #~ msgid "" #~ "How to convert your existing file systems to utilize journaling, and what " #~ "options to use in [.filename]#/etc/fstab# to mount them." #~ msgstr "" #~ "Как преобразовать существующую файловую систему, в систему, использующую " #~ "журналирование, и какие опции монтирования использовать в [.filename]#/" #~ "etc/fstab#." #~ msgid "How to implement journaling in new (empty) partitions." #~ msgstr "Как реализовать журналирование на новых (пустых) разделах." #~ msgid "" #~ "The procedure described here is intended for preparing a new installation " #~ "where no actual user data is stored on the disk yet. While it is " #~ "possible to modify and extend this procedure for systems already in " #~ "production, you should _backup_ all important data before doing so. " #~ "Messing around with disks and partitions at a low level can lead to fatal " #~ "mistakes and data loss." #~ msgstr "" #~ "Процедура, описанная здесь, подразумевает подготовку к новой установке, в " #~ "которой на дисках ещё нет пользовательских данных. Так как эту процедуру " #~ "можно модифицировать и расширить на системы, которые уже используются, " #~ "вам настоятельно рекомендуется сделать _резервную копию_ всех ценных " #~ "данных. Путаница в низкоуровневых операциях с дисками и разделами может " #~ "привести к фатальным ошибкам и потере данных." #~ msgid "" #~ "The journaling provided by GEOM in FreeBSD 7._X_ is not file system " #~ "specific (unlike for example the ext3 file system in Linux(R)) but is " #~ "functioning at the block level. Though this means it can be applied to " #~ "different file systems, for FreeBSD 7.0-RELEASE, it can only be used on " #~ "UFS2." #~ msgstr "" #~ "Журналирование, предоставляемое системой GEOM в FreeBSD 7._X_, не " #~ "является особенностью файловой системы (в отличие от, например, файловой " #~ "системы ext3 в Linux(R)), оно функционирует на блочном уровне. А это " #~ "значит, что оно может быть применено к разным типам файловых систем, " #~ "однако для FreeBSD 7.0-RELEASE журналирование может быть применено только " #~ "для UFS2." #~ msgid "" #~ "When a file system is journaled, some disk space is needed to keep the " #~ "journal itself. The disk space that holds the actual data is referred to " #~ "as the __data provider__, while the one that holds the journal is " #~ "referred to as the __journal provider__. The data and journal providers " #~ "need to be on different partitions when journaling an existing (non-" #~ "empty) partition. When journaling a new partition, you have the option " #~ "to use a single provider for both data and journal. In any case, the " #~ "`gjournal` command combines both providers to create the final journaled " #~ "file system. For example:" #~ msgstr "" #~ "Когда файловая система журналируется, некоторая часть дискового " #~ "пространства требуется для хранения самого журнала. Дисковое " #~ "пространство, содержащее данные, называется __поставщиком данных (data " #~ "provider)__, а часть пространства, содержащая журнал, называется " #~ "__поставщиком журнала (journal provider)__. Поставщики данных и журнала " #~ "должны быть на разных разделах, если журналирование достраивается к " #~ "содержащему данные разделу. А если журналирование включается для нового " #~ "раздела, у вас есть возможность использовать один поставщик для данных и " #~ "журнала. В любом из двух вышеупомянутых случаев команда `gjournal` " #~ "задействует поставщики и создаст конечную журналируемую файловую систему. " #~ "Например:" #~ msgid "" #~ "You wish to journal your [.filename]#/usr# file system, stored in [." #~ "filename]#/dev/ad0s1f# (which already contains data)." #~ msgstr "" #~ "Вы намереваетесь журналировать файловую систему [.filename]#/usr#, " #~ "размещенную на [.filename]#/dev/ad0s1f#, файловая система уже содержит " #~ "данные." #~ msgid "" #~ "You reserved some free disk space in a partition in [.filename]#/dev/" #~ "ad0s1g#." #~ msgstr "" #~ "Вы зарезервировали часть дискового пространства на разделе [.filename]#/" #~ "dev/ad0s1g#." #~ msgid "" #~ "The amount of disk space you need to reserve for the journal provider " #~ "depends on the usage load of the file system and not on the size of the " #~ "data provider. For example on a typical office desktop, a 1 GB journal " #~ "provider for the [.filename]#/usr# file system will suffice, while a " #~ "machine that deals with heavy disk I/O (i.e. video editing) may need " #~ "more. A kernel panic will occur if the journal space is exhausted before " #~ "it has a chance to be committed." #~ msgstr "" #~ "Размер дискового пространства, отводимого под поставщик журнала, зависит " #~ "от нагруженности файловой системы, а не от размера самого поставщика " #~ "данных. Например, для типичного настольного компьютера достаточно отвести " #~ "1 Гб под поставщик журнала для файловой системы [.filename]#/usr#, в то " #~ "время как компьютеру, имеющему интенсивный дисковый ввод/вывод (например, " #~ "редактирование видео) может потребоваться больше. Если свободное место на " #~ "поставщике журнала заканчивается раньше, чем происходит сброс журнала на " #~ "диск, - вы получите панику ядра." #~ msgid "" #~ "The journal sizes suggested here, are highly unlikely to cause problems " #~ "in typical desktop use (such as web browsing, word processing and " #~ "playback of media files). If your workload includes intense disk " #~ "activity, use the following rule for maximum reliability: Your RAM size " #~ "should fit in 30% of the journal provider's space. For example, if your " #~ "system has 1 GB RAM, create an approximately 3.3 GB journal provider. " #~ "(Multiply your RAM size with 3.3 to obtain the size of the journal)." #~ msgstr "" #~ "Очень маловероятно то, что размеры журнала, предложенные здесь, станут " #~ "причиной проблем с обычным настольным компьютером (на котором вы " #~ "просматриваете веб-страницы, обрабатываете текст или проигрываете " #~ "мультимедийные файлы). Если работа вашего компьютера подразумевает " #~ "интенсивную дисковую активность, то для обеспечения стабильности следует " #~ "придерживаться следующего правила: размер ОЗУ должен уместиться в 30% " #~ "размера, отведенного под журнал. Например, если в вашем компьютере " #~ "установлен 1 Гб ОЗУ, создайте под поставщик журнала раздел размером около " #~ "3.3 Гб. (Умножьте размер ОЗУ в 3.3 раза, чтоб получить размер журнала)." #~ msgid "" #~ "A typical desktop machine usually has one hard disk that stores both the " #~ "OS and user data. Arguably, the default partitioning scheme selected by " #~ "sysinstall is more or less suitable: A desktop machine does not need a " #~ "large [.filename]#/var# partition, while [.filename]#/usr# is allocated " #~ "the bulk of the disk space, since user data and a lot of packages are " #~ "installed into its subdirectories." #~ msgstr "" #~ "Типичный настольный компьютер обычно имеет один жёсткий диск, на котором " #~ "хранится как операционная система, так и пользовательские данные. " #~ "Вероятно, что схема разбития винчестера (по умолчанию), выбранная в меню " #~ "Sysinstall, является более или менее подходящей: настольному компьютеру " #~ "не требуется большой раздел [.filename]#/var#, в то время, как для " #~ "раздела [.filename]#/usr# выделяется значительный объём дискового " #~ "пространства, ввиду того, что пользовательские данные и множество пакетов " #~ "инсталлируются в подкаталоги [.filename]#/usr#." #~ msgid "" #~ "The default partitioning (the one obtained by pressing kbd:[A] at the " #~ "FreeBSD partition editor, called Disklabel) does not leave any " #~ "unallocated space. Each partition that will be journaled, requires " #~ "another partition for the journal. Since the [.filename]#/usr# partition " #~ "is the largest, it makes sense to shrink this partition slightly, to " #~ "obtain the space required for journaling." #~ msgstr "" #~ "Разбиение по умолчанию (получаемое при нажатии kbd:[A] в редакторе " #~ "разделов FreeBSD, называемом Disklabel) не оставляет свободного места. " #~ "Каждый подлежащий журналированию раздел требует отдельного раздела для " #~ "журнала. Ввиду того, что раздел [.filename]#/usr# - наибольший, есть " #~ "смысл немного уменьшить его размер, чтобы получить пространство, " #~ "необходимое для журнала." #~ msgid "" #~ "In our example, an 80 GB disk is used. The following screenshot shows " #~ "the default partitions created by Disklabel during installation:" #~ msgstr "" #~ "В нашем примере используется жёсткий диск размером 80 Гб. Следующий " #~ "скриншот показывает результаты разбиения по умолчанию, выполненного при " #~ "помощи Disklabel в процессе установки операционной системы:" #, no-wrap #~ msgid "disklabel1.png" #~ msgstr "disklabel1.png" #~ msgid "" #~ "If this is more or less what you need, it is very easy to adjust for " #~ "journaling. Simply use the arrow keys to move the highlight to the [." #~ "filename]#/usr# partition and press kbd:[D] to delete it." #~ msgstr "" #~ "Если это разбиение более или менее вас устраивает, то его легко " #~ "модифицировать для журналирования. Используйте клавиши со стрелками для " #~ "того, чтобы выделить раздел, отведенный под [.filename]#/usr#, потом " #~ "нажмите kbd:[D] чтобы удалить его." #~ msgid "" #~ "Now, move the highlight to the disk name at the top of the screen and " #~ "press kbd:[C] to create a new partition for [.filename]#/usr#. This new " #~ "partition should be smaller by 1 GB (if you intend to journal [." #~ "filename]#/usr# only), or 2 GB (if you intend to journal both [." #~ "filename]#/usr# and [.filename]#/var#). From the pop-up that appears, " #~ "opt to create a file system, and type [.filename]#/usr# as the mount " #~ "point." #~ msgstr "" #~ "Теперь переведите подсвечивание к имени диска, находящемуся вверху " #~ "экрана, и нажмите kbd:[C] - создайте новый раздел [.filename]#/usr#. " #~ "Новый раздел должен быть меньше на 1 Гб (если вы собираетесь " #~ "журналировать только [.filename]#/usr#) или на 2 Гб (если журналированию " #~ "подлежат как [.filename]#/usr#, так и [.filename]#/var#). Во всплывающем " #~ "окне выберите \"создать файловую систему\" и укажите [.filename]#/usr# " #~ "точкой монтирования." #~ msgid "" #~ "Should you journal the [.filename]#/var# partition? Normally, journaling " #~ "makes sense on quite large partitions. You may decide not to journal [." #~ "filename]#/var#, although doing so on a typical desktop will cause no " #~ "harm. If the file system is lightly used (quite probable for a desktop) " #~ "you may wish to allocate less disk space for its journal." #~ msgstr "" #~ "Следует ли журналировать [.filename]#/var# раздел? Обычно есть смысл " #~ "журналировать большие разделы. Вы можете решить не журналировать [." #~ "filename]#/var#, однако журналирование на обычном настольном компьютере " #~ "не причинит вреда. Если файловая система не нагружена (что типично для " #~ "настольной системы), то можно выделить меньше дискового пространства под " #~ "журнал." #~ msgid "" #~ "In our example, we journal both [.filename]#/usr# and [.filename]#/var#. " #~ "You may of course adjust the procedure to your own needs." #~ msgstr "" #~ "В этом примере подразумевается журналирование двух файловых систем: [." #~ "filename]#/usr# и [.filename]#/var#. Естественно, вы можете " #~ "подкорректировать процедуру под свои задачи." #~ msgid "" #~ "To keep things as easy going as possible, we are going to use sysinstall " #~ "to create the partitions required for journaling. However, during " #~ "installation, sysinstall insists on asking a mount point for each " #~ "partition you create. At this point, you do not have any mount points " #~ "for the partitions that will hold the journals, and in reality you __do " #~ "not even need them__. These are not partitions that we are ever going to " #~ "mount somewhere." #~ msgstr "" #~ "Чтобы не усложнять описываемую методику, для создания разделов, " #~ "необходимых для размещения журналов, мы будем использовать утилиту " #~ "Sysinstall. Однако, во время установки утилита Sysinstall требует " #~ "указания точек монтирования для каждого созданного вами раздела. Но " #~ "разделы, содержащие журналы, вам никогда и никуда монтировать не придется." #~ msgid "" #~ "To avoid these problems with sysinstall, we are going to create the " #~ "journal partitions as swap space. Swap is never mounted, and sysinstall " #~ "has no problem creating as many swap partitions as needed. After the " #~ "first reboot, [.filename]#/etc/fstab# will have to be edited, and the " #~ "extra swap space entries removed." #~ msgstr "" #~ "Чтобы избежать вопросов о точках монтирования, мы создадим разделы под " #~ "журналы и установим их тип в swap. Раздел, предназначенный для свопа, " #~ "никогда и никуда не монтируется, плюс к тому, утилита Sysinstall " #~ "позволяет создавать столько разделов под своп, сколько необходимо. После " #~ "первой перезагрузки необходимо подредактировать файл [.filename]#/etc/" #~ "fstab#, удалив в нём лишние записи о своп-разделах." #~ msgid "" #~ "To create the swap, again use the arrow keys to move the highlight to the " #~ "top of Disklabel screen, so that the disk name itself is highlighted. " #~ "Then press kbd:[N], enter the desired size (_1024M_), and select \"swap " #~ "space\" from the pop-up menu that appears. Repeat for every journal you " #~ "wish to create. In our example, we create two partitions to provide for " #~ "the journals of [.filename]#/usr# and [.filename]#/var#. The final " #~ "result is shown in the following screenshot:" #~ msgstr "" #~ "Для создания своп-раздела, используя клавиши со стрелками, перемещайте " #~ "подсвечивание к верхней части экрана в утилите Disklabel так, чтобы стало " #~ "подсвеченным имя диска. Потом, нажмите kbd:[N], введите необходимый " #~ "размер раздела (_1024M_), а после - выберите во всплывшем окне \"swap " #~ "space\". Повторите эти шаги для всех оставшихся журналов. В этом примере " #~ "мы создаем два раздела, на которых будут размещаться журналы для [." #~ "filename]#/usr# и [.filename]#/var#. Конечный результат показан на " #~ "следующем скриншоте:" #, no-wrap #~ msgid "disklabel2.png" #~ msgstr "disklabel2.png" #~ msgid "" #~ "When you have completed creating the partitions, we suggest you write " #~ "down the partition names, and mount points, so you can easily refer to " #~ "this information during the configuration phase. This will help " #~ "alleviate mistakes that may damage your installation. The following " #~ "table shows our notes for the sample configuration:" #~ msgstr "" #~ "По завершении создания разделов мы рекомендуем вам записать на бумагу " #~ "названия разделов и их точек монтирования: с этой информацией вы будете " #~ "сверяться во время конфигурирования. Это также поможет уменьшить " #~ "количество ошибок, приводящих к повреждению установки. Следующая табличка " #~ "отображает наши заметки, сделанные для данного примера:" #, no-wrap #~ msgid "Mount Point" #~ msgstr "Точка монтирования" #, no-wrap #~ msgid "ad0s1d" #~ msgstr "ad0s1d" #, no-wrap #~ msgid "ad0s1h" #~ msgstr "ad0s1h" #, no-wrap #~ msgid "ad0s1f" #~ msgstr "ad0s1f" #, no-wrap #~ msgid "ad0s1g" #~ msgstr "ad0s1g" #~ msgid "" #~ "Continue the installation as you would normally do. We would however " #~ "suggest you postpone installation of third party software (packages) " #~ "until you have completely setup journaling." #~ msgstr "" #~ "Дальше продолжайте обычную установку. Однако, мы рекомендуем вам отложить " #~ "инсталляцию приложений сторонних разработчиков (пакетов) до полной " #~ "настройки журналирования." #, no-wrap #~ msgid "Booting for the first time" #~ msgstr "Первая загрузка" #~ msgid "" #~ "Your system will come up normally, but you will need to edit [.filename]#/" #~ "etc/fstab# and remove the extra swap partitions you created for the " #~ "journals. Normally, the swap partition you will actually use is the one " #~ "with the \"b\" suffix (i.e. ad0s1b in our example). Remove all other " #~ "swap space entries and reboot so that FreeBSD will stop using them." #~ msgstr "" #~ "Ваша система загрузится нормально, однако вам необходимо будет " #~ "подредактировать [.filename]#/etc/fstab# и удалить те лишние своп-" #~ "разделы, которые вы создавали под журналы. Как правило, в названии файла " #~ "устройства, созданного автоматически утилитой Sysinstall, присутствует " #~ "суффикс \"b\" (в нашем примере это ad0s1b). Удалите другие записи о своп-" #~ "разделах и перезагрузите компьютер, после чего FreeBSD перестанет их " #~ "использовать." #~ msgid "" #~ "Having prepared all the required partitions, it is quite easy to " #~ "configure journaling. We will need to switch to single user mode, so " #~ "login as `root` and type:" #~ msgstr "" #~ "Подготовив необходимые разделы, перейдем к конфигурированию " #~ "журналирования. Нам будет необходимо загрузиться в однопользовательском " #~ "режиме, для этого залогинимся пользователем `root` и напечатаем:" #~ msgid "Load the module required for journaling:" #~ msgstr "Загрузите модуль ядра, необходимый для журналирования:" #~ msgid "" #~ "Now, use your notes to determine which partition will be used for each " #~ "journal. In our example, [.filename]#/usr# is [.filename]#ad0s1f# and " #~ "its journal will be [.filename]#ad0s1g#, while [.filename]#/var# is [." #~ "filename]#ad0s1d# and will be journaled to [.filename]#ad0s1h#. The " #~ "following commands are required:" #~ msgstr "" #~ "На данном этапе сверьтесь со своими записями и определите, какие разделы " #~ "будут использоваться под какой журнал. В нашем примере [.filename]#/usr# " #~ "располагается на [.filename]#ad0s1f#, а его журнал будет располагаться на " #~ "[.filename]#ad0s1g#, и, по аналогии, для [.filename]#/var#: файловая " #~ "система располагается на [.filename]#ad0s1d#, а её журнал - на [." #~ "filename]#ad0s1h#. Наберите следующие команды:" #~ msgid "" #~ "If the last sector of either partition is used, `gjournal` will return an " #~ "error. You will have to run the command using the `-f` flag to force an " #~ "overwrite, i.e.:" #~ msgstr "" #~ "Если последний сектор любого из двух разделов (поставщиков данных) " #~ "используется, команда `gjournal` возвратит ошибку. Вам необходимо будет " #~ "использовать флаг `-F` для принудительной перезаписи, например:" #~ msgid "" #~ "Since this is a new installation, it is highly unlikely that anything " #~ "will be actually overwritten." #~ msgstr "" #~ "Так как это - новая установка, очень маловероятен факт, что что-нибудь " #~ "будет действительно переписано." #~ msgid "" #~ "At this point, two new devices are created, namely [.filename]#ad0s1d." #~ "journal# and [.filename]#ad0s1f.journal#. These represent the [." #~ "filename]#/var# and [.filename]#/usr# partitions we have to mount. " #~ "Before mounting, we must however set the journal flag on them and clear " #~ "the Soft Updates flag:" #~ msgstr "" #~ "На данном этапе созданы два устройства: [.filename]#ad0s1d.journal# и [." #~ "filename]#ad0s1f.journal#. Они представляют [.filename]#/var# и [." #~ "filename]#/usr# соответственно. Перед монтированием, нам необходимо " #~ "установить флаг журналирования и снять флаг механизма Soft Updates:" #, no-wrap #~ msgid "" #~ "# tunefs -J enable -n disable ad0s1d.journal\n" #~ "tunefs: gjournal set\n" #~ "tunefs: soft updates cleared\n" #~ msgstr "" #~ "# tunefs -J enable -n disable ad0s1d.journal\n" #~ "tunefs: gjournal set\n" #~ "tunefs: soft updates cleared\n" #, no-wrap #~ msgid "" #~ "# tunefs -J enable -n disable ad0s1f.journal\n" #~ "tunefs: gjournal set\n" #~ "tunefs: soft updates cleared\n" #~ msgstr "" #~ "# tunefs -J enable -n disable ad0s1f.journal\n" #~ "tunefs: gjournal set\n" #~ "tunefs: soft updates cleared\n" #, no-wrap #~ msgid "" #~ "ad0: 76293MB XEC XE800JD-00HBC0 08.02D08 at ata0-master SATA150\n" #~ "GEOM_JOURNAL: Journal 2948326772: ad0s1g contains journal.\n" #~ "GEOM_JOURNAL: Journal 3193218002: ad0s1h contains journal.\n" #~ "GEOM_JOURNAL: Journal 3193218002: ad0s1d contains data.\n" #~ "GEOM_JOURNAL: Journal ad0s1d clean.\n" #~ "GEOM_JOURNAL: Journal 2948326772: ad0s1f contains data.\n" #~ "GEOM_JOURNAL: Journal ad0s1f clean.\n" #~ msgstr "" #~ "ad0: 76293MB XEC XE800JD-00HBC0 08.02D08 at ata0-master SATA150\n" #~ "GEOM_JOURNAL: Journal 2948326772: ad0s1g contains journal.\n" #~ "GEOM_JOURNAL: Journal 3193218002: ad0s1h contains journal.\n" #~ "GEOM_JOURNAL: Journal 3193218002: ad0s1d contains data.\n" #~ "GEOM_JOURNAL: Journal ad0s1d clean.\n" #~ "GEOM_JOURNAL: Journal 2948326772: ad0s1f contains data.\n" #~ "GEOM_JOURNAL: Journal ad0s1f clean.\n" #~ msgid "" #~ "The journal probably fills up before it has a chance to get committed " #~ "(flushed) to disk. Keep in mind the size of the journal depends on the " #~ "usage load, and not the size of the data provider. If your disk activity " #~ "is high, you need a larger partition for the journal. See the note in " #~ "the crossref:gjournal-desktop[understanding-journaling, Understanding " #~ "Journaling in FreeBSD] section." #~ msgstr "" #~ "Вероятно, что журнал заполняется раньше, чем происходит сброс его на " #~ "диск. Помните, размер журнала зависит от загруженности диска, а не от " #~ "размера поставщика данных. Если загрузка диска высокая, вам потребуется " #~ "раздел большего размера для журнала. См. замечания в разделе crossref:" #~ "gjournal-desktop[understanding-journaling, Understanding Journaling in " #~ "FreeBSD]." #, no-wrap #~ msgid "" #~ "# tunefs -J disable -n enable ad0s1f\n" #~ "tunefs: gjournal cleared\n" #~ "tunefs: soft updates set\n" #~ msgstr "" #~ "# tunefs -J disable -n enable ad0s1f\n" #~ "tunefs: gjournal cleared\n" #~ "tunefs: soft updates set\n" diff --git a/documentation/content/ru/articles/hubs/_index.adoc b/documentation/content/ru/articles/hubs/_index.adoc index dd51367d2f..6ea3db7d5b 100644 --- a/documentation/content/ru/articles/hubs/_index.adoc +++ b/documentation/content/ru/articles/hubs/_index.adoc @@ -1,336 +1,336 @@ --- authors: - author: 'Jun Kuriyama' email: kuriyama@FreeBSD.org - author: 'Valentino Vaschetto' email: logo@FreeBSD.org - author: 'Daniel Lang' email: dl@leo.org - author: 'Ken Smith' email: kensmith@FreeBSD.org description: 'Полное руководство по зеркалированию веб-сайта FreeBSD, FTP-серверов и многого другого' tags: ["Mirroring", "FreeBSD", "Hub"] title: 'Поддержка зеркал FreeBSD' trademarks: ["freebsd", "general"] --- = Поддержка зеркал FreeBSD :doctype: article :toc: macro :toclevels: 1 :icons: font :sectnums: :sectnumlevels: 6 :source-highlighter: rouge :experimental: :images-path: articles/hubs/ ifdef::env-beastie[] ifdef::backend-html5[] include::shared/authors.adoc[] include::shared/mirrors.adoc[] include::shared/releases.adoc[] include::shared/attributes/attributes-{{% lang %}}.adoc[] include::shared/{{% lang %}}/teams.adoc[] include::shared/{{% lang %}}/mailing-lists.adoc[] include::shared/{{% lang %}}/urls.adoc[] :imagesdir: ../../../images/{images-path} endif::[] ifdef::backend-pdf,backend-epub3[] include::../../../../shared/asciidoctor.adoc[] endif::[] endif::[] ifndef::env-beastie[] include::../../../../../shared/asciidoctor.adoc[] endif::[] [.abstract-title] Аннотация Рабочий вариант статьи, описывающей процесс создания и поддержки зеркала FreeBSD и адресованной администраторам зеркал. ''' toc::[] [NOTE] ==== На текущий момент заявки на подключение новых зеркал не принимаются. ==== [[mirror-contact]] == Контактная информация Координаторы системы зеркал доступны по электронной почте по адресу mailto:mirror-admin@FreeBSD.org[mirror-admin@FreeBSD.org]. Помимо этого, существует {freebsd-hubs}. [[mirror-requirements]] == Требования к зеркалам FreeBSD [[mirror-diskspace]] === Дисковое пространство Одним из наиболее важных требований является дисковое пространство. В зависимости от набора релизов, архитектур и степени полноты зеркала вам может потребоваться огромный объём диска. Не лишним будет помнить, что _официальное_ зеркало, скорее всего, должно быть полным. Веб-страницы всегда должны зеркалироваться полностью. Кроме того, учтите, что приводимые оценки объёма относятся к состоянию на момент последнего редактирования данной статьи ({rel120-current}-RELEASE/{rel113-current}-RELEASE). Дальнейший процесс разработки и последующие релизы только увеличат требуемый объём. Кроме того, разумно будет зарезервировать некоторое (10-20%) дополнительное пространство спокойствия ради. Вот некоторые оценки объёма: * Полное зеркало FTP: 1.4 TB * Комплект изменений CTM: 10 GB * Веб-страницы: 1 GB Текущее использование диска зеркалом FTP можно посмотреть на link:ftp://ftp.FreeBSD.org/pub/FreeBSD/dir.sizes[ftp://ftp.FreeBSD.org/pub/FreeBSD/dir.sizes]. [[mirror-bandwidth]] === Требования к сетевой связности и пропускной способности Разумеется, у вас должно быть подключение к интернет. Требуемая пропускная способность ваших каналов зависит от предполагаемого профиля использования вашего зеркала. Если вы собираетесь копировать некоторые части FreeBSD для локального использования на вашей машине или в интранете, требования могут быть много мягче, чем для публичного зеркала. Для официального зеркала необходимая пропускная способность увеличивается ещё больше. Мы можем дать лишь очень грубые оценки: * Зеркало для локального доступа: фактически минимум не определен, но канал шириной менее 2 Mbps может сделать процесс обновления мучительно медленным. * Неофициальное публичное зеркало: 34 Mbps выглядит неплохо для начала. * Официальное зеркало: рекомендуется канал шириной более 100 Mbps; кроме того, ваша машина должна стоять как можно ближе к граничным маршрутизаторам вашей сети. [[mirror-system]] === Системные требования, процессор и память Эти требования в первую очередь определяются максимальным ожидаемым количеством клиентов (устанавливается администратором сервера). Также, на требуемые ресурсы влияет список сервисов, которые вы будете предоставлять. Зеркала FTP и/или HTTP не требуют особенно много ресурсов. Будьте на чеку, если планируете предоставлять rsync. Выбор rsync может иметь огромное влияние на требования к аппаратным ресурсам, поскольку rsync признан "прожорливым" по памяти. Вот некоторые советы по конфигурации аппаратной части сервера. Для умеренно посещаемого сайта, предоставляющего rsync, можно использовать процессор с частотой 800MHz - 1 GHz и по крайней мере 512MB памяти. Скорее всего, данная конфигурация может считаться минимальной для _официального_ зеркала. Для регулярно посещаемого сайта вам потребуется больше памяти (хорошим стартом будет 2GB) и больше процессорной мощности, что может означать требование многопроцессорной (SMP) платформы. Кроме того, вам потребуется быстрая дисковая подсистема, в первую очередь, для работы с репозиторием SVN (крайне рекомендуем RAID). Контроллер SCSI, оборудованный собственной памятью, также может ощутимо ускорить процесс, поскольку большая часть сервисов связана с большим количеством дисковых запросов небольшого размера. [[mirror-services]] === Предоставляемые сервисы Всякое зеркало должно предоставлять набор основных сервисов. Помимо требуемого минимального набора, существуют дополнительные сервисы, которые администратор сервера может пожелать предоставлять. Этот раздел описывает, какие сервисы вы можете предоставлять, и какие действия для этого потребуются от вас. [[mirror-serv-ftp]] ==== FTP (требуется для FTP зеркала) Это один из наиболее базовых сервисов; его предоставление требуется для каждого зеркала, распространяющего файлы FreeBSD по FTP. Доступ по FTP должен быть анонимным, и не должны применяться какие-либо ограничения по соотношению объёма передано/принято (что вообще является, на наш взгляд, странным подходом). Закачка (upload) файлов на сервер не требуется (и _должна_ быть запрещена в разделе FreeBSD). Кроме того, архив файлов FreeBSD должен быть доступен с путем [.filename]#/pub/FreeBSD#. Для предоставления анонимного FTP доступа может быть использован целый ряд программ (перечислены в алфавитном порядке). * `/usr/libexec/ftpd`: базовый FTP-даемон FreeBSD. Не забудьте прочитать man:ftpd[8]. * package:ftp/ncftpd[]: коммерческий пакет, свободен для использования в учебных целях. * package:ftp/oftpd[]: FTP-даемон, написанный в основном с точки зрения защищенности. * package:ftp/proftpd[]: Модульный и очень гибкий FTP-даемон. * package:ftp/pure-ftpd[]: Еще один FTP-даемон, разработанный с позиций защищенности. * package:ftp/twoftpd[]: См. предыдущий пункт. * package:ftp/vsftpd[]: "очень защищенный" ("very secure") ftpd. ftpd, proftpd и, возможно, ncftpd являются наиболее часто встречающимися FTP серверами. Прочие распространены среди существующих зеркал в существенно меньшей степени. Дополнительным поводом для рассмотрения может являться возможность гибко ограничивать количество одновременных соединений, что поможет вам удержать в нужных рамках потребление пропускной способности ваших каналов и машинные ресурсы. [[mirror-serv-rsync]] ==== Rsync (необязательный сервис для FTP зеркала) rsync часто используется для предоставления доступа к FTP-области FreeBSD, чтобы другие зеркала могли синхронизироваться по вашему. Протокол rsync во многом отличается от FTP, в частности, он гораздо гуманнее с точки зрения пропускной способности каналов, поскольку не требует передачи измененного файла целиком (передаются лишь различия). Взамен rsync требует значительных объёмов памяти. Размер каждого процесса зависит от размера синхронизируемого модуля (в основном от количества каталогов и файлов). rsync может использовать в качестве транспортного протокола `rsh` или `ssh` (по умолчанию); также, может использоваться внутренний протокол rsync (этот метод предпочтителен для публичных rsync-серверов). Поддерживается авторизация клиентов и различные ограничения. Для протокола rsync существует единственный пакет: * package:net/rsync[] [[mirror-serv-http]] ==== HTTP (требуется для веб-страниц, дополнителен для FTP зеркал) Если вы хотите поддерживать зеркало веб-страниц FreeBSD, вам потребуется установить веб-сервер. Дополнительно, вы можете предоставлять HTTP доступ к FTP-набору файлов FreeBSD. Выбор веб-сервера остаётся на усмотрение администратора зеркала. Некоторые из наиболее популярных веб-серверов перечислены ниже: * package:www/apache24[]: Apache - самый широко распространённый в Интернете веб-сервер, активно используемый проектом FreeBSD. -* package:www/boa[]: Boa - это однозадачный HTTP-сервер. В отличие от традиционных веб-серверов, он не создает отдельные процессы для каждого входящего соединения и не запускает множество копий самого себя для обработки множества соединений. Тем не менее, он должен обеспечивать значительно более высокую производительность для чисто статического контента. +* package:www/boa[]: Boa - это однозадачный HTTP-сервер. В отличие от традиционных веб-серверов, он не создаёт отдельные процессы для каждого входящего соединения и не запускает множество копий самого себя для обработки множества соединений. Тем не менее, он должен обеспечивать значительно более высокую производительность для чисто статического контента. * package:www/cherokee[]: Cherokee — это очень быстрый, гибкий и простой в настройке веб-сервер. Он поддерживает распространённые современные технологии: FastCGI, SCGI, PHP, CGI, SSL/TLS-шифрование соединений, виртуальные хосты, аутентификацию пользователей, динамическое кодирование и балансировку нагрузки. Также он генерирует журналы, совместимые с Apache. * package:www/lighttpd[]: lighttpd — это безопасный, быстрый, совместимый и очень гибкий веб-сервер, оптимизированный для высокопроизводительных сред. По сравнению с другими веб-серверами, он имеет очень низкое потребление памяти и эффективно распределяет нагрузку на процессор. * package:www/nginx[]: nginx — это высокопроизводительный веб-сервер с низким потреблением памяти и ключевыми функциями для построения современной и эффективной веб-инфраструктуры. Возможности включают HTTP-сервер, обратный прокси для HTTP и почты, кэширование, балансировку нагрузки, сжатие, ограничение запросов, мультиплексирование и повторное использование соединений, выгрузку SSL и потоковую передачу HTTP-медиа. * package:www/thttpd[]: Если вам необходимо обслуживать большое количество статического контента, вы можете обнаружить, что использование приложения, такого как thttpd, более эффективно по сравнению с другими. Оно также оптимизировано для отличной производительности в FreeBSD. [[mirror-howto]] == Как вести зеркало FreeBSD Теперь вам известно, какая потребуется машина и как предоставлять сервисы, но не как получить их самому. :-) В этом разделе описывается процесс ведения зеркала и поддержания его в актуальном состоянии, в том числе какие инструменты использовать и какие сайты выбирать в качестве источников для синхронизации. [[mirror-ftp-rsync]] === Зеркалирование FTP-области Файлы, доступные по FTP, составляют большую часть зеркала. Они включают __дистрибутивные наборы__, необходимые для установки по сети, __ветви (branches)__, в которых отражено текущее состояние исходных текстов, _образы ISO_ для записи компакт-дисков с дистрибутивами для установки, образами "живых" файловых систем и пакетами, дерево портов, исходные дистрибутивы для сборки портов и кучу готовых пакетов. И, разумеется, все вышеописанное - для разных версий FreeBSD и различных архитектур. Наиболее эффективным будет синхронизация FTP-области при помощи rsync. Для этого следует установить пакет package:net/rsync[], который был описан в разделе <>. Поскольку доступ по протоколу rsync не является обязательным, выбранный вами сайт может его не поддерживать. Возможно, вам придется немного поискать в сетевой окрестности зеркало, поддерживающее rsync. [NOTE] ==== Поскольку от количества клиентов rsync ощутимо зависит загрузка сервера, большинство администраторов вводят ограничения доступа. Для поддержания зеркала вам следует связаться с администратором сайта, с которым вы будете синхронизироваться, для уточнения локальных правил и, возможно, для внесения в них исключения для вас (поскольку вы также поддерживаете зеркало). ==== Строка для синхронизации FreeBSD по rsync выглядит примерно так: [source, shell] .... % rsync -vaHz --delete rsync://ftp4.de.FreeBSD.org/FreeBSD/ /pub/FreeBSD/ .... -Загляните в документацию по rsync, также доступную по адресу http://rsync.samba.org/[http://rsync.samba.org/] за дополнительной информацией по различным опциям rsync. Обратите внимание, что в случае синхронизации модуля целиком (а не отдельного каталога) необходимо явно указать результирующий каталог, потому что каталог с именем модуля (в данном случае "FreeBSD") не создается. Для поддержания актуальности вам потребуется создать скрипт для запуска подобной команды из man:cron[8]. +Загляните в документацию по rsync, также доступную по адресу http://rsync.samba.org/[http://rsync.samba.org/] за дополнительной информацией по различным опциям rsync. Обратите внимание, что в случае синхронизации модуля целиком (а не отдельного каталога) необходимо явно указать результирующий каталог, потому что каталог с именем модуля (в данном случае "FreeBSD") не создаётся. Для поддержания актуальности вам потребуется создать скрипт для запуска подобной команды из man:cron[8]. [[mirror-www]] === Зеркалирование страниц WWW [WARNING] ==== После перевода документации на Hugo/Asciidoctor 2021-01-25, зеркалирование веб-сайта с помощью rsync больше не работает. ==== Ведутся исследования по реализации зеркала веб-сайта с использованием extref:{handbook}mirrors/[официальной инфраструктуры]. Для прежних зеркал веб-сайтов способ достичь зеркалирования сегодня — это собрать веб-сайт локально с соответствующим адресом, на котором он будет размещён. [source, shell] .... % cd website && env HUGO_baseURL="https://www.XX.freebsd.org/" make .... Проверьте дополнительные сведения о инструментах сборки в extref:{fdp-primer}overview/[Проект документации FreeBSD: введение для новых участников, overview-quick-start]. //// [source,shell] .... % rsync -vaHz --delete rsync://bit0.us-west.freebsd.org/FreeBSD-www-data/ /usr/local/www/ .... //// [NOTE] ==== Обратите внимание, что сайт был разделён на www.FreeBSD.org и docs.FreeBSD.org, и между ними есть ссылки; кроме того, на данный момент переменная `HUGO_baseURL` не охватывает все ссылки, поэтому зеркалирование сайта не рекомендуется. ==== [[mirror-pkgs]] === Зеркалирование пакетов Из-за очень высоких требований к пропускной способности, хранилищу и администрированию проект FreeBSD принял решение не разрешать публичные зеркала пакетов. Для сайтов с большим количеством машин может быть выгодно запустить кэширующий HTTP-прокси для процесса man:pkg[8]. Или конкретные пакеты и их зависимости можно загрузить, выполнив что-то вроде следующего: [source, shell] .... % pkg fetch -d -o /usr/local/mirror vim .... После загрузки этих пакетов необходимо сгенерировать метаданные репозитория, выполнив: [source, shell] .... % pkg repo /usr/local/mirror .... После загрузки пакетов и генерации метаданных репозитория предоставьте пакеты клиентским машинам через HTTP. Дополнительную информацию можно найти на man-страницах man:pkg[8], в частности на странице man:pkg-repo[8]. [[mirror-how-often]] === Как часто синхронизироваться? Каждое зеркало должно обновляться как минимум раз в день. Конечно, потребуется скрипт с блокировкой, чтобы предотвратить одновременный запуск нескольких копий, который будет запускаться из man:cron[8]. Поскольку почти каждый администратор делает это по-своему, конкретные инструкции предоставить невозможно. Это может работать примерно так: [.procedure] ==== . Создайте скрипт с командой, которая запустит нужное приложение для обновления зеркала. Рекомендуем использовать скрипт на языке обычного `/bin/sh`. . Добавьте команд перенаправления вывода, чтобы записать диагностику работы в файл. . Попробуйте, как ваш скрипт работает. По завершении проверьте журналы. . При помощи утилиты man:crontab[1] добавьте ваш скрипт в таблицу регулярных заданий man:crontab[5] соответствующего пользователя. Это должен быть пользователь, отличный от пользователя FTP-даемона, чтобы файлы в FTP-области без атрибута "чтение для всех" не были доступны анонимным FTP-пользователям. Данное свойство используется для тестирования перед выходом новых релизов, для того чтобы удостовериться, что все официальные зеркала содержат все необходимые файлы к моменту официального объявления релиза. ==== Некоторые рекомендуемые установки частоты обновления: * FTP-набор: раз в сутки * WWW-страницы: раз в сутки [[mirror-where]] == С какого сервера синхронизироваться Это важный вопрос, так что мы попытаемся пояснить, откуда берутся ответы. Для начала повторим ещё несколько раз: _никогда не синхронизируйтесь с ftp.FreeBSD.org_. [[mirror-where-organization]] === Организация системы зеркал Зеркала организуются по странам. Имена хостов всех официальных зеркал построены по принципу `ftpN.CC.FreeBSD.org`, где _CC_ (country code) - домен верхнего уровня страны, где расположено зеркало, _N_ - номер зеркала в данной стране. Этот же принцип применим к именам хостов `wwwN.CC.FreeBSD.org` и т.п. Кроме того, есть зеркала без доменной части, обозначающей страну. Все они имеют очень хорошие внешние каналы и обслуживают большое число одновременных соединений. Имя `ftp.FreeBSD.org` на самом деле указывает на две машины, одна из которых в настоящее время находится в Дании, а другая в США. Ни одна из этих машин _НЕ_ является основным сайтом, и потому не должна использоваться для синхронизации. Масса документации для "живых" пользователей указывает на `ftp.FreeBSD.org`, так что автоматическим системам ведения зеркал следует выбирать другие источники синхронизации. -Кроме того, существует иерархия зеркал в терминах их удаленности от центра, или __слоях__. Основные сайты могут быть описаны как __Зеркала нулевого слоя__. Зеркала, синхронизирующиеся по ним, считаются __слоем 1__, следующие - _слоем 2_ и т.д. Официальные сайты приглашаются на низкие слои, однако следует помнить, что чем меньше номер слоя, тем выше требования к зеркалу, как было описано в <>. Помимо того, доступ к зеркалам 1 слоя может быть ограничен; безусловно ограничен доступ к основным сайтам. Иерархия _слоев_ не отражается в DNS и, вообще говоря, нигде (кроме мастер-сайтов) не документирована. Тем не менее, официальные зеркала с малыми (1-4, как правило) номерами обычно представляют первый слой. (Это грубая оценка, и ни в коем случае не правило). +Кроме того, существует иерархия зеркал в терминах их удалённости от центра, или __слоях__. Основные сайты могут быть описаны как __Зеркала нулевого слоя__. Зеркала, синхронизирующиеся по ним, считаются __слоем 1__, следующие - _слоем 2_ и т.д. Официальные сайты приглашаются на низкие слои, однако следует помнить, что чем меньше номер слоя, тем выше требования к зеркалу, как было описано в <>. Помимо того, доступ к зеркалам 1 слоя может быть ограничен; безусловно ограничен доступ к основным сайтам. Иерархия _слоев_ не отражается в DNS и, вообще говоря, нигде (кроме мастер-сайтов) не документирована. Тем не менее, официальные зеркала с малыми (1-4, как правило) номерами обычно представляют первый слой. (Это грубая оценка, и ни в коем случае не правило). [[mirror-where-where]] === Так откуда же мне синхронизироваться? Главное - НЕ с `ftp.FreeBSD.org`. Короткий ответ: с зеркала, которое расположено недалеко от вас в терминах Интернет, и/или доступ к которому наилучший. [[mirror-where-simple]] ==== Я хочу получить копию зеркала хоть откуда-нибудь! Если у вас нет особых намерений или требований, применимо утверждение в crossref:hubs[mirror-where-where, Так откуда же мне синхронизироваться?]. Это означает: [.procedure] ==== . Выберите те из них, с которыми вам работать быстрее всего (меньшее число промежуточных узлов и время отклика), и которые предоставляют нужные вам сервисы (такие как rsync). . Свяжитесь с администраторами выбранного сервера, опишите ваши запросы и уточните их правила. . Сконфигурируйте ваше зеркало, как описывалось выше. ==== [[mirror-where-official]] ==== Я поддерживаю официальное зеркало, какой сайт мне выбрать? В основном, правила, описанные в crossref:hubs[mirror-where-simple, Я хочу получить копию зеркала хоть откуда-нибудь!], применимы. Дополнительно можно убедиться, что выбранный сайт принадлежит низкому слою. Другие соображения относительно _официальных_ зеркал описаны в <>. [[mirror-where-master]] ==== Мне нужен доступ к основным сайтам! При наличии достаточных причин вы можете получить доступ к одному из основных сайтов. Доступ к ним ограничен; существуют специальные правила их использования. Наличие у вас статуса _официального_ зеркала, безусловно, является хорошим подспорьем. В противном случае убедитесь, что ваша страна действительно нуждается ещё в одном зеркале. Если их уже три или более, сначала свяжитесь с администратором соответствующей зоны DNS (mailto:hostmaster@CC.FreeBSD.org[hostmaster@CC.FreeBSD.org]) или напишите в {freebsd-hubs}. Тот, кто помог вам стать _официальным_ зеркалом, должен был помочь вам получить доступ к соответствующему вышестоящему хосту — либо к одному из основных сайтов, либо к подходящему сайту уровня Tier-1. Если этого не произошло, вы можете отправить письмо по адресу mailto:mirror-admin@FreeBSD.org[mirror-admin@FreeBSD.org], чтобы запросить помощь в этом вопросе. Существует один основной сайт для синхронизации набора файлов FTP. [[mirror-where-master-ftp]] ===== ftp-master.FreeBSD.org Это основной сервер для синхронизации FTP набора. В дополнение к FTP, `ftp-master.FreeBSD.org` поддерживает доступ по rsync. Использование этих протоколов описано в crossref:hubs[mirror-ftp-rsync, Mirroring the FTP Site]. Приветствуется предоставление зеркалами _1 уровня_ доступа к FTP-области по протоколу rsync. [[mirror-official]] == Официальные зеркала Официальные зеркала обладают следующим свойствами * a) имеют запись в домене `FreeBSD.org` (обычно типа CNAME). * b) присутствуют в списке официальных зеркал в Руководстве по FreeBSD и другой документации. На настоящий момент это все, что отличает их от прочих зеркал. Официальные зеркала не обязательно принадлежат к __Первому уровню__, однако, вряд ли можно найти зеркало __уровня 1__, не являющееся официальным. [[mirror-official-requirements]] === Отдельные требования к официальным зеркалам 1 уровня Описать требования для всех официальных зеркал не так просто, поскольку проект FreeBSD достаточно мягок в этом отношении. Несколько проще указать, что требуется от __официальных зеркал уровня 1__. Прочие официальные зеркала должны рассматривать этот список как __настойчивые пожелания__. Зеркала 1 уровня должны: * поддерживать полный список файлов * предоставлять доступ для других зеркал * обеспечивать доступ по протоколам ftp и rsync Кроме того, администратор такого зеркала должен быть подписан на {freebsd-hubs}. См. extref:{handbook}eresources[здесь, eresources-mail] для дополнительной информации о подписке. [IMPORTANT] ==== Очень важно для администратора хаба, особенно администраторов хаба уровня Tier-1, проверять https://www.FreeBSD.org/releng/[график выпусков] следующего релиза FreeBSD. Это важно, потому что это позволит вам узнать, когда запланирован выход следующего релиза, и, таким образом, даст вам время подготовиться к большому всплеску трафика, который последует за ним. Кроме того, важно поддерживать актуальность зеркал (в особенности зеркал уровня 1). Если Зеркало1 не синхронизировалось в течение длительного времени, то зеркала следующего уровня будут синхронизироваться по устаревшей информации и т.д. Поддерживайте актуальность ваших зеркал! ==== [[mirror-official-become]] === Как стать официальным зеркалом? Обратитесь к администраторам кластера, как указано в документации по адресу https://www.FreeBSD.org/administration/#t-clusteradm. [[mirror-statpages]] == Статистика некоторых зеркал Вот ссылки на страницы статистики ваших любимых зеркал (иначе говоря, единственных, кто предоставляет такую статистику). [[mirror-statpagesftp]] === Статистика FTP сайтов * ftp.is.FreeBSD.org - mailto:hostmaster@is.FreeBSD.org[hostmaster@is.FreeBSD.org] - http://www.rhnet.is/status/draupnir/draupnir.html[ (Bandwidth)] http://www.rhnet.is/status/ftp/ftp-notendur.html[(FTP processes)] http://www.rhnet.is/status/ftp/http-notendur.html[(HTTP processes)] * ftp2.ru.FreeBSD.org - mailto:mirror@macomnet.ru[mirror@macomnet.ru] - http://mirror.macomnet.net/mrtg/mirror.macomnet.net_195.128.64.25.html[(Bandwidth)] http://mirror.macomnet.net/mrtg/mirror.macomnet.net_proc.html[(HTTP and FTP users)] diff --git a/documentation/content/ru/articles/hubs/_index.po b/documentation/content/ru/articles/hubs/_index.po index 1f10a1e8f4..06964bc90e 100644 --- a/documentation/content/ru/articles/hubs/_index.po +++ b/documentation/content/ru/articles/hubs/_index.po @@ -1,1209 +1,1209 @@ # SOME DESCRIPTIVE TITLE # Copyright (C) YEAR The FreeBSD Project # This file is distributed under the same license as the FreeBSD Documentation package. # Vladlen Popolitov , 2025, 2026. msgid "" msgstr "" "Project-Id-Version: FreeBSD Documentation VERSION\n" "POT-Creation-Date: 2025-11-08 16:17+0000\n" -"PO-Revision-Date: 2026-03-04 20:01+0000\n" +"PO-Revision-Date: 2026-04-05 04:45+0000\n" "Last-Translator: Vladlen Popolitov \n" "Language-Team: Russian \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "X-Generator: Weblate 4.17\n" #. type: YAML Front Matter: description #: documentation/content/en/articles/hubs/_index.adoc:1 #, no-wrap msgid "The all in one guide for mirroring the FreeBSD website, FTP servers, and more" msgstr "Полное руководство по зеркалированию веб-сайта FreeBSD, FTP-серверов и многого другого" #. type: Title = #: documentation/content/en/articles/hubs/_index.adoc:1 #: documentation/content/en/articles/hubs/_index.adoc:17 #, no-wrap msgid "Mirroring FreeBSD" msgstr "Поддержка зеркал FreeBSD" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:50 msgid "Abstract" msgstr "Аннотация" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:52 msgid "" "An in-progress article on how to mirror FreeBSD, aimed at hub administrators." msgstr "" "Рабочий вариант статьи, описывающей процесс создания и поддержки зеркала " "FreeBSD и адресованной администраторам зеркал." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:54 msgid "'''" msgstr "'''" #. type: delimited block = 4 #: documentation/content/en/articles/hubs/_index.adoc:60 msgid "We are not accepting new community mirrors at this time." msgstr "На текущий момент заявки на подключение новых зеркал не принимаются." #. type: Title == #: documentation/content/en/articles/hubs/_index.adoc:63 #, no-wrap msgid "Contact Information" msgstr "Контактная информация" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:67 msgid "" "The Mirror System Coordinators can be reached through email at mailto:mirror-" "admin@FreeBSD.org[mirror-admin@FreeBSD.org]. There is also a {freebsd-hubs}." msgstr "" "Координаторы системы зеркал доступны по электронной почте по адресу mailto:" "mirror-admin@FreeBSD.org[mirror-admin@FreeBSD.org]. Помимо этого, существует " "{freebsd-hubs}." #. type: Title == #: documentation/content/en/articles/hubs/_index.adoc:69 #, no-wrap msgid "Requirements for FreeBSD Mirrors" msgstr "Требования к зеркалам FreeBSD" #. type: Title === #: documentation/content/en/articles/hubs/_index.adoc:72 #, no-wrap msgid "Disk Space" msgstr "Дисковое пространство" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:82 msgid "" "Disk space is one of the most important requirements. Depending on the set " "of releases, architectures, and degree of completeness you want to mirror, a " "huge amount of disk space may be consumed. Also keep in mind that " "_official_ mirrors are probably required to be complete. The web pages " "should always be mirrored completely. Also note that the numbers stated " "here are reflecting the current state (at {rel120-current}-RELEASE/{rel113-" "current}-RELEASE). Further development and releases will only increase the " "required amount. Also make sure to keep some (ca. 10-20%) extra space " "around just to be sure. Here are some approximate figures:" msgstr "" "Одним из наиболее важных требований является дисковое пространство. В " "зависимости от набора релизов, архитектур и степени полноты зеркала вам " "может потребоваться огромный объём диска. Не лишним будет помнить, что " "_официальное_ зеркало, скорее всего, должно быть полным. Веб-страницы всегда " "должны зеркалироваться полностью. Кроме того, учтите, что приводимые оценки " "объёма относятся к состоянию на момент последнего редактирования данной " "статьи ({rel120-current}-RELEASE/{rel113-current}-RELEASE). Дальнейший " "процесс разработки и последующие релизы только увеличат требуемый объём. " "Кроме того, разумно будет зарезервировать некоторое (10-20%) дополнительное " "пространство спокойствия ради. Вот некоторые оценки объёма:" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:84 msgid "Full FTP Distribution: 1.4 TB" msgstr "Полное зеркало FTP: 1.4 TB" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:85 msgid "CTM deltas: 10 GB" msgstr "Комплект изменений CTM: 10 GB" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:86 msgid "Web pages: 1GB" msgstr "Веб-страницы: 1 GB" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:88 msgid "" "The current disk usage of FTP Distribution can be found at link:ftp://ftp." "FreeBSD.org/pub/FreeBSD/dir.sizes[ftp://ftp.FreeBSD.org/pub/FreeBSD/dir." "sizes]." msgstr "" "Текущее использование диска зеркалом FTP можно посмотреть на link:ftp://ftp." "FreeBSD.org/pub/FreeBSD/dir.sizes[ftp://ftp.FreeBSD.org/pub/FreeBSD/dir." "sizes]." #. type: Title === #: documentation/content/en/articles/hubs/_index.adoc:90 #, no-wrap msgid "Network Connection/Bandwidth" msgstr "Требования к сетевой связности и пропускной способности" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:97 msgid "" "Of course, you need to be connected to the Internet. The required bandwidth " "depends on your intended use of the mirror. If you just want to mirror some " "parts of FreeBSD for local use at your site/intranet, the demand may be much " "smaller than if you want to make the files publicly available. If you " "intend to become an official mirror, the bandwidth required will be even " "higher. We can only give rough estimates here:" msgstr "" "Разумеется, у вас должно быть подключение к интернет. Требуемая пропускная " "способность ваших каналов зависит от предполагаемого профиля использования " "вашего зеркала. Если вы собираетесь копировать некоторые части FreeBSD для " "локального использования на вашей машине или в интранете, требования могут " "быть много мягче, чем для публичного зеркала. Для официального зеркала " "необходимая пропускная способность увеличивается ещё больше. Мы можем дать " "лишь очень грубые оценки:" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:99 msgid "" "Local site, no public access: basically no minimum, but < 2 Mbps could make " "syncing too slow." msgstr "" "Зеркало для локального доступа: фактически минимум не определен, но канал " "шириной менее 2 Mbps может сделать процесс обновления мучительно медленным." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:100 msgid "Unofficial public site: 34 Mbps is probably a good start." msgstr "Неофициальное публичное зеркало: 34 Mbps выглядит неплохо для начала." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:101 msgid "" "Official site: > 100 Mbps is recommended, and your host should be connected " "as close as possible to your border router." msgstr "" "Официальное зеркало: рекомендуется канал шириной более 100 Mbps; кроме того, " "ваша машина должна стоять как можно ближе к граничным маршрутизаторам вашей " "сети." #. type: Title === #: documentation/content/en/articles/hubs/_index.adoc:103 #, no-wrap msgid "System Requirements, CPU, RAM" msgstr "Системные требования, процессор и память" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:111 msgid "" "One thing this depends on the expected number of clients, which is " "determined by the server's policy. It is also affected by the types of " "services you want to offer. Plain FTP or HTTP services may not require a " "huge amount of resources. Watch out if you provide rsync. This can have a " "huge impact on CPU and memory requirements as it is considered a memory " "hog. The following are just examples to give you a very rough hint." msgstr "" "Эти требования в первую очередь определяются максимальным ожидаемым " "количеством клиентов (устанавливается администратором сервера). Также, на " "требуемые ресурсы влияет список сервисов, которые вы будете предоставлять. " "Зеркала FTP и/или HTTP не требуют особенно много ресурсов. Будьте на чеку, " "если планируете предоставлять rsync. Выбор rsync может иметь огромное " "влияние на требования к аппаратным ресурсам, поскольку rsync признан " "\"прожорливым\" по памяти. Вот некоторые советы по конфигурации аппаратной " "части сервера." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:114 msgid "" "For a moderately visited site that offers rsync, you might consider a " "current CPU with around 800MHz - 1 GHz, and at least 512MB RAM. This is " "probably the minimum you want for an _official_ site." msgstr "" "Для умеренно посещаемого сайта, предоставляющего rsync, можно использовать " "процессор с частотой 800MHz - 1 GHz и по крайней мере 512MB памяти. Скорее " "всего, данная конфигурация может считаться минимальной для _официального_ " "зеркала." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:116 msgid "" "For a frequently used site you definitely need more RAM (consider 2GB as a " "good start) and possibly more CPU, which could also mean that you need to go " "for a SMP system." msgstr "" "Для регулярно посещаемого сайта вам потребуется больше памяти (хорошим " "стартом будет 2GB) и больше процессорной мощности, что может означать " "требование многопроцессорной (SMP) платформы." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:120 msgid "" "You also want to consider a fast disk subsystem. Operations on the SVN " "repository require a fast disk subsystem (RAID is highly advised). A SCSI " "controller that has a cache of its own can also speed up things since most " "of these services incur a large number of small modifications to the disk." msgstr "" "Кроме того, вам потребуется быстрая дисковая подсистема, в первую очередь, " "для работы с репозиторием SVN (крайне рекомендуем RAID). Контроллер SCSI, " "оборудованный собственной памятью, также может ощутимо ускорить процесс, " "поскольку большая часть сервисов связана с большим количеством дисковых " "запросов небольшого размера." #. type: Title === #: documentation/content/en/articles/hubs/_index.adoc:122 #, no-wrap msgid "Services to Offer" msgstr "Предоставляемые сервисы" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:127 msgid "" "Every mirror site is required to have a set of core services available. In " "addition to these required services, there are a number of optional services " "that server administrators may choose to offer. This section explains which " "services you can provide and how to go about implementing them." msgstr "" "Всякое зеркало должно предоставлять набор основных сервисов. Помимо " "требуемого минимального набора, существуют дополнительные сервисы, которые " "администратор сервера может пожелать предоставлять. Этот раздел описывает, " "какие сервисы вы можете предоставлять, и какие действия для этого " "потребуются от вас." #. type: Title ==== #: documentation/content/en/articles/hubs/_index.adoc:129 #, no-wrap msgid "FTP (required for FTP Fileset)" msgstr "FTP (требуется для FTP зеркала)" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:135 msgid "" "This is one of the most basic services, and it is required for each mirror " "offering public FTP distributions. FTP access must be anonymous, and no " "upload/download ratios are allowed (a ridiculous thing anyway). Upload " "capability is not required (and _must_ never be allowed for the FreeBSD file " "space). Also the FreeBSD archive should be available under the path [." "filename]#/pub/FreeBSD#." msgstr "" "Это один из наиболее базовых сервисов; его предоставление требуется для " "каждого зеркала, распространяющего файлы FreeBSD по FTP. Доступ по FTP " "должен быть анонимным, и не должны применяться какие-либо ограничения по " "соотношению объёма передано/принято (что вообще является, на наш взгляд, " "странным подходом). Закачка (upload) файлов на сервер не требуется (и " "_должна_ быть запрещена в разделе FreeBSD). Кроме того, архив файлов FreeBSD " "должен быть доступен с путем [.filename]#/pub/FreeBSD#." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:137 msgid "" "There is a lot of software available which can be set up to allow anonymous " "FTP (in alphabetical order)." msgstr "" "Для предоставления анонимного FTP доступа может быть использован целый ряд " "программ (перечислены в алфавитном порядке)." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:139 msgid "" "`/usr/libexec/ftpd`: FreeBSD's own ftpd can be used. Be sure to read man:" "ftpd[8]." msgstr "" "`/usr/libexec/ftpd`: базовый FTP-даемон FreeBSD. Не забудьте прочитать man:" "ftpd[8]." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:140 msgid "package:ftp/ncftpd[]: A commercial package, free for educational use." msgstr "" "package:ftp/ncftpd[]: коммерческий пакет, свободен для использования в " "учебных целях." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:141 msgid "package:ftp/oftpd[]: An ftpd designed with security as a main focus." msgstr "" "package:ftp/oftpd[]: FTP-даемон, написанный в основном с точки зрения " "защищенности." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:142 msgid "package:ftp/proftpd[]: A modular and very flexible ftpd." msgstr "package:ftp/proftpd[]: Модульный и очень гибкий FTP-даемон." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:143 msgid "package:ftp/pure-ftpd[]: Another ftpd developed with security in mind." msgstr "" "package:ftp/pure-ftpd[]: Еще один FTP-даемон, разработанный с позиций " "защищенности." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:144 msgid "package:ftp/twoftpd[]: As above." msgstr "package:ftp/twoftpd[]: См. предыдущий пункт." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:145 msgid "package:ftp/vsftpd[]: The \"very secure\" ftpd." msgstr "package:ftp/vsftpd[]: \"очень защищенный\" (\"very secure\") ftpd." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:149 msgid "" "FreeBSD's `ftpd`, `proftpd` and maybe `ncftpd` are among the most commonly " "used FTPds. The others do not have a large userbase among mirror sites. " "One thing to consider is that you may need flexibility in limiting how many " "simultaneous connections are allowed, thus limiting how much network " "bandwidth and system resources are consumed." msgstr "" "ftpd, proftpd и, возможно, ncftpd являются наиболее часто встречающимися FTP " "серверами. Прочие распространены среди существующих зеркал в существенно " "меньшей степени. Дополнительным поводом для рассмотрения может являться " "возможность гибко ограничивать количество одновременных соединений, что " "поможет вам удержать в нужных рамках потребление пропускной способности " "ваших каналов и машинные ресурсы." #. type: Title ==== #: documentation/content/en/articles/hubs/_index.adoc:151 #, no-wrap msgid "Rsync (optional for FTP Fileset)" msgstr "Rsync (необязательный сервис для FTP зеркала)" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:161 msgid "" "Rsync is often offered for access to the contents of the FTP area of " "FreeBSD, so other mirror sites can use your system as their source. The " "protocol is different from FTP in many ways. It is much more bandwidth " "friendly, as only differences between files are transferred instead of whole " "files when they change. Rsync does require a significant amount of memory " "for each instance. The size depends on the size of the synced module in " "terms of the number of directories and files. Rsync can use `rsh` and `ssh` " "(now default) as a transport, or use its own protocol for stand-alone access " "(this is the preferred method for public rsync servers). Authentication, " "connection limits, and other restrictions may be applied. There is just one " "software package available:" msgstr "" "rsync часто используется для предоставления доступа к FTP-области FreeBSD, " "чтобы другие зеркала могли синхронизироваться по вашему. Протокол rsync во " "многом отличается от FTP, в частности, он гораздо гуманнее с точки зрения " "пропускной способности каналов, поскольку не требует передачи измененного " "файла целиком (передаются лишь различия). Взамен rsync требует значительных " "объёмов памяти. Размер каждого процесса зависит от размера синхронизируемого " "модуля (в основном от количества каталогов и файлов). rsync может " "использовать в качестве транспортного протокола `rsh` или `ssh` (по " "умолчанию); также, может использоваться внутренний протокол rsync (этот " "метод предпочтителен для публичных rsync-серверов). Поддерживается " "авторизация клиентов и различные ограничения. Для протокола rsync существует " "единственный пакет:" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:163 msgid "package:net/rsync[]" msgstr "package:net/rsync[]" #. type: Title ==== #: documentation/content/en/articles/hubs/_index.adoc:165 #, no-wrap msgid "HTTP (required for Web Pages, Optional for FTP Fileset)" msgstr "HTTP (требуется для веб-страниц, дополнителен для FTP зеркал)" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:171 msgid "" "If you want to offer the FreeBSD web pages, you will need to install a web " "server. You may optionally offer the FTP fileset via HTTP. The choice of " "web server software is left up to the mirror administrator. Some of the " "most popular choices are:" msgstr "" "Если вы хотите поддерживать зеркало веб-страниц FreeBSD, вам потребуется " "установить веб-сервер. Дополнительно, вы можете предоставлять HTTP доступ к " "FTP-набору файлов FreeBSD. Выбор веб-сервера остаётся на усмотрение " "администратора зеркала. Некоторые из наиболее популярных веб-серверов " "перечислены ниже:" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:173 msgid "" "package:www/apache24[]: Apache is still one of the most widely deployed web " "servers on the Internet. It is used extensively by the FreeBSD Project." msgstr "" "package:www/apache24[]: Apache - самый широко распространённый в Интернете " "веб-сервер, активно используемый проектом FreeBSD." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:174 msgid "" "package:www/boa[]: Boa is a single-tasking HTTP server. Unlike traditional " "web servers, it does not fork for each incoming connection, nor does it fork " "many copies of itself to handle multiple connections. Although, it should " "provide considerably great performance for purely static content." msgstr "" "package:www/boa[]: Boa - это однозадачный HTTP-сервер. В отличие от " -"традиционных веб-серверов, он не создает отдельные процессы для каждого " +"традиционных веб-серверов, он не создаёт отдельные процессы для каждого " "входящего соединения и не запускает множество копий самого себя для " "обработки множества соединений. Тем не менее, он должен обеспечивать " "значительно более высокую производительность для чисто статического контента." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:175 msgid "" "package:www/cherokee[]: Cherokee is a very fast, flexible and easy to " "configure web server. It supports the widespread technologies nowadays: " "FastCGI, SCGI, PHP, CGI, SSL/TLS encrypted connections, vhosts, users " "authentication, on the fly encoding and load balancing. It also generates " "Apache compatible log files." msgstr "" "package:www/cherokee[]: Cherokee — это очень быстрый, гибкий и простой в " "настройке веб-сервер. Он поддерживает распространённые современные " "технологии: FastCGI, SCGI, PHP, CGI, SSL/TLS-шифрование соединений, " "виртуальные хосты, аутентификацию пользователей, динамическое кодирование и " "балансировку нагрузки. Также он генерирует журналы, совместимые с Apache." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:176 msgid "" "package:www/lighttpd[]: lighttpd is a secure, fast, compliant and very " "flexible web server which has been optimized for high-performance " "environments. It has a very low memory footprint compared to other web " "servers and takes care of cpu-load." msgstr "" "package:www/lighttpd[]: lighttpd — это безопасный, быстрый, совместимый и " "очень гибкий веб-сервер, оптимизированный для высокопроизводительных сред. " "По сравнению с другими веб-серверами, он имеет очень низкое потребление " "памяти и эффективно распределяет нагрузку на процессор." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:177 msgid "" "package:www/nginx[]: nginx is a high performance edge web server with a low " "memory footprint and key features to build a modern and efficient web " "infrastructure. Features include a HTTP server, HTTP and mail reverse proxy, " "caching, load balancing, compression, request throttling, connection " "multiplexing and reuse, SSL offload and HTTP media streaming." msgstr "" "package:www/nginx[]: nginx — это высокопроизводительный веб-сервер с низким " "потреблением памяти и ключевыми функциями для построения современной и " "эффективной веб-инфраструктуры. Возможности включают HTTP-сервер, обратный " "прокси для HTTP и почты, кэширование, балансировку нагрузки, сжатие, " "ограничение запросов, мультиплексирование и повторное использование " "соединений, выгрузку SSL и потоковую передачу HTTP-медиа." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:178 msgid "" "package:www/thttpd[]: If you are going to be serving a large amount of " "static content you may find that using an application such as thttpd is more " "efficient than others. It is also optimized for excellent performance on " "FreeBSD." msgstr "" "package:www/thttpd[]: Если вам необходимо обслуживать большое количество " "статического контента, вы можете обнаружить, что использование приложения, " "такого как thttpd, более эффективно по сравнению с другими. Оно также " "оптимизировано для отличной производительности в FreeBSD." #. type: Title == #: documentation/content/en/articles/hubs/_index.adoc:180 #, no-wrap msgid "How to Mirror FreeBSD" msgstr "Как вести зеркало FreeBSD" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:184 msgid "" "Ok, now you know the requirements and how to offer the services, but not how " "to get it. :-) This section explains how to actually mirror the various " "parts of FreeBSD, what tools to use, and where to mirror from." msgstr "" "Теперь вам известно, какая потребуется машина и как предоставлять сервисы, " "но не как получить их самому. :-) В этом разделе описывается процесс ведения " "зеркала и поддержания его в актуальном состоянии, в том числе какие " "инструменты использовать и какие сайты выбирать в качестве источников для " "синхронизации." #. type: Title === #: documentation/content/en/articles/hubs/_index.adoc:186 #, no-wrap msgid "Mirroring the FTP Site" msgstr "Зеркалирование FTP-области" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:191 msgid "" "The FTP area is the largest amount of data that needs to be mirrored. It " "includes the _distribution sets_ required for network installation, the " "_branches_ which are actually snapshots of checked-out source trees, the " "_ISO Images_ to write CD-ROMs with the installation distribution, a live " "file system, and a snapshot of the ports tree. All of course for various " "FreeBSD versions, and various architectures." msgstr "" "Файлы, доступные по FTP, составляют большую часть зеркала. Они включают " "__дистрибутивные наборы__, необходимые для установки по сети, __ветви " "(branches)__, в которых отражено текущее состояние исходных текстов, _образы " "ISO_ для записи компакт-дисков с дистрибутивами для установки, образами " "\"живых\" файловых систем и пакетами, дерево портов, исходные дистрибутивы " "для сборки портов и кучу готовых пакетов. И, разумеется, все вышеописанное - " "для разных версий FreeBSD и различных архитектур." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:197 msgid "" "The best way to mirror the FTP area is rsync. You can install the port " "package:net/rsync[] and then use rsync to sync with your upstream host. " "rsync is already mentioned in crossref:hubs[mirror-serv-rsync, Rsync " "(optional for FTP Fileset)]. Since rsync access is not required, your " "preferred upstream site may not allow it. You may need to hunt around a " "little bit to find a site that allows rsync access." msgstr "" "Наиболее эффективным будет синхронизация FTP-области при помощи rsync. Для " "этого следует установить пакет package:net/rsync[], который был описан в " "разделе <>. Поскольку доступ по протоколу rsync не " "является обязательным, выбранный вами сайт может его не поддерживать. " "Возможно, вам придется немного поискать в сетевой окрестности зеркало, " "поддерживающее rsync." #. type: delimited block = 4 #: documentation/content/en/articles/hubs/_index.adoc:202 msgid "" "Since the number of rsync clients will have a significant impact on the " "server machine, most admins impose limitations on their server. For a " "mirror, you should ask the site maintainer you are syncing from about their " "policy, and maybe an exception for your host (since you are a mirror)." msgstr "" "Поскольку от количества клиентов rsync ощутимо зависит загрузка сервера, " "большинство администраторов вводят ограничения доступа. Для поддержания " "зеркала вам следует связаться с администратором сайта, с которым вы будете " "синхронизироваться, для уточнения локальных правил и, возможно, для внесения " "в них исключения для вас (поскольку вы также поддерживаете зеркало)." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:205 msgid "A command line to mirror FreeBSD might look like:" msgstr "Строка для синхронизации FreeBSD по rsync выглядит примерно так:" #. type: delimited block . 4 #: documentation/content/en/articles/hubs/_index.adoc:209 #, no-wrap msgid "% rsync -vaHz --delete rsync://ftp4.de.FreeBSD.org/FreeBSD/ /pub/FreeBSD/\n" msgstr "% rsync -vaHz --delete rsync://ftp4.de.FreeBSD.org/FreeBSD/ /pub/FreeBSD/\n" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:213 msgid "" "Consult the documentation for rsync, which is also available at http://rsync." "samba.org/[http://rsync.samba.org/], about the various options to be used " "with rsync. If you sync the whole module (unlike subdirectories), be aware " "that the module-directory (here \"FreeBSD\") will not be created, so you " "cannot omit the target directory. Also you might want to set up a script " "framework that calls such a command via man:cron[8]." msgstr "" "Загляните в документацию по rsync, также доступную по адресу http://rsync." "samba.org/[http://rsync.samba.org/] за дополнительной информацией по " "различным опциям rsync. Обратите внимание, что в случае синхронизации модуля " "целиком (а не отдельного каталога) необходимо явно указать результирующий " "каталог, потому что каталог с именем модуля (в данном случае \"FreeBSD\") не " -"создается. Для поддержания актуальности вам потребуется создать скрипт для " +"создаётся. Для поддержания актуальности вам потребуется создать скрипт для " "запуска подобной команды из man:cron[8]." #. type: Title === #: documentation/content/en/articles/hubs/_index.adoc:215 #, no-wrap msgid "Mirroring the WWW Pages" msgstr "Зеркалирование страниц WWW" #. type: delimited block = 4 #: documentation/content/en/articles/hubs/_index.adoc:220 msgid "" "Since doc migration to Hugo/Asciidoctor on 2021-01-25, mirroring the website " "with rsync no longer works." msgstr "" "После перевода документации на Hugo/Asciidoctor 2021-01-25, зеркалирование " "веб-сайта с помощью rsync больше не работает." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:223 msgid "" "There are ongoing studies to implement a website mirror with the extref:" "{handbook}mirrors/[official infrastructure]." msgstr "" "Ведутся исследования по реализации зеркала веб-сайта с использованием extref:" "{handbook}mirrors/[официальной инфраструктуры]." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:225 msgid "" "For the former website mirrors, a way to achieve mirroring the website today " "is building the website locally with the corresponding address it will be " "hosted." msgstr "" "Для прежних зеркал веб-сайтов способ достичь зеркалирования сегодня — это " "собрать веб-сайт локально с соответствующим адресом, на котором он будет " "размещён." #. type: delimited block . 4 #: documentation/content/en/articles/hubs/_index.adoc:229 #, no-wrap msgid "% cd website && env HUGO_baseURL=\"https://www.XX.freebsd.org/\" make\n" msgstr "% cd website && env HUGO_baseURL=\"https://www.XX.freebsd.org/\" make\n" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:232 msgid "" "Check for more details about the build tools on extref:{fdp-primer}overview/" "[FreeBSD Documentation Project Primer for New Contributors, overview-quick-" "start] book." msgstr "" "Проверьте дополнительные сведения о инструментах сборки в extref:{fdp-primer}" "overview/[Проект документации FreeBSD: введение для новых участников, " "overview-quick-start]." #. [source,shell] #. .... #. % rsync -vaHz --delete rsync://bit0.us-west.freebsd.org/FreeBSD-www-data/ /usr/local/www/ #. .... #. type: delimited block = 4 #: documentation/content/en/articles/hubs/_index.adoc:243 msgid "" "Notice the website was split into www.FreeBSD.org and docs.FreeBSD.org, and " "there are links between them; plus, at this moment, `HUGO_baseURL` variable " "won't cover all links, this way, mirroring the website is discouraged." msgstr "" "Обратите внимание, что сайт был разделён на www.FreeBSD.org и docs.FreeBSD." "org, и между ними есть ссылки; кроме того, на данный момент переменная " "`HUGO_baseURL` не охватывает все ссылки, поэтому зеркалирование сайта не " "рекомендуется." #. type: Title === #: documentation/content/en/articles/hubs/_index.adoc:246 #, no-wrap msgid "Mirroring Packages" msgstr "Зеркалирование пакетов" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:251 msgid "" "Due to very high requirements of bandwidth, storage and administration the " "FreeBSD Project has decided not to allow public mirrors of packages. For " "sites with lots of machines, it might be advantagous to run a caching HTTP " "proxy for the man:pkg[8] process. Alternatively specific packages and their " "dependencies can be fetched by running something like the following:" msgstr "" "Из-за очень высоких требований к пропускной способности, хранилищу и " "администрированию проект FreeBSD принял решение не разрешать публичные " "зеркала пакетов. Для сайтов с большим количеством машин может быть выгодно " "запустить кэширующий HTTP-прокси для процесса man:pkg[8]. Или конкретные " "пакеты и их зависимости можно загрузить, выполнив что-то вроде следующего:" #. type: delimited block . 4 #: documentation/content/en/articles/hubs/_index.adoc:255 #, no-wrap msgid "% pkg fetch -d -o /usr/local/mirror vim\n" msgstr "% pkg fetch -d -o /usr/local/mirror vim\n" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:258 msgid "" "Once those packages have been fetched, the repository metadata must be " "generated by running:" msgstr "" "После загрузки этих пакетов необходимо сгенерировать метаданные репозитория, " "выполнив:" #. type: delimited block . 4 #: documentation/content/en/articles/hubs/_index.adoc:262 #, no-wrap msgid "% pkg repo /usr/local/mirror\n" msgstr "% pkg repo /usr/local/mirror\n" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:266 msgid "" "Once the packages have been fetched and the metadata for the repository has " "been generated, serve the packages up to the client machines via HTTP. For " "additional information see the man pages for man:pkg[8], specifically the " "man:pkg-repo[8] page." msgstr "" "После загрузки пакетов и генерации метаданных репозитория предоставьте " "пакеты клиентским машинам через HTTP. Дополнительную информацию можно найти " "на man-страницах man:pkg[8], в частности на странице man:pkg-repo[8]." #. type: Title === #: documentation/content/en/articles/hubs/_index.adoc:268 #, no-wrap msgid "How Often Should I Mirror?" msgstr "Как часто синхронизироваться?" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:274 msgid "" "Every mirror should be updated at a minimum of once per day. Certainly a " "script with locking to prevent multiple runs happening at the same time will " "be needed to run from man:cron[8]. Since nearly every admin does this in " "their own way, specific instructions cannot be provided. It could work " "something like this:" msgstr "" "Каждое зеркало должно обновляться как минимум раз в день. Конечно, " "потребуется скрипт с блокировкой, чтобы предотвратить одновременный запуск " "нескольких копий, который будет запускаться из man:cron[8]. Поскольку почти " "каждый администратор делает это по-своему, конкретные инструкции " "предоставить невозможно. Это может работать примерно так:" #. type: delimited block = 4 #: documentation/content/en/articles/hubs/_index.adoc:278 msgid "" "Put the command to run your mirroring application in a script. Use of a " "plain `/bin/sh` script is recommended." msgstr "" "Создайте скрипт с командой, которая запустит нужное приложение для " "обновления зеркала. Рекомендуем использовать скрипт на языке обычного `/bin/" "sh`." #. type: delimited block = 4 #: documentation/content/en/articles/hubs/_index.adoc:279 msgid "" "Add some output redirections so diagnostic messages are logged to a file." msgstr "" "Добавьте команд перенаправления вывода, чтобы записать диагностику работы в " "файл." #. type: delimited block = 4 #: documentation/content/en/articles/hubs/_index.adoc:280 msgid "Test if your script works. Check the logs." msgstr "Попробуйте, как ваш скрипт работает. По завершении проверьте журналы." #. type: delimited block = 4 #: documentation/content/en/articles/hubs/_index.adoc:281 msgid "" "Use man:crontab[1] to add the script to the appropriate user's man:" "crontab[5]. This should be a different user than what your FTP daemon runs " "as so that if file permissions inside your FTP area are not world-readable " "those files cannot be accessed by anonymous FTP. This is used to \"stage\" " "releases - making sure all of the official mirror sites have all of the " "necessary release files on release day." msgstr "" "При помощи утилиты man:crontab[1] добавьте ваш скрипт в таблицу регулярных " "заданий man:crontab[5] соответствующего пользователя. Это должен быть " "пользователь, отличный от пользователя FTP-даемона, чтобы файлы в FTP-" "области без атрибута \"чтение для всех\" не были доступны анонимным FTP-" "пользователям. Данное свойство используется для тестирования перед выходом " "новых релизов, для того чтобы удостовериться, что все официальные зеркала " "содержат все необходимые файлы к моменту официального объявления релиза." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:284 msgid "Here are some recommended schedules:" msgstr "Некоторые рекомендуемые установки частоты обновления:" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:286 msgid "FTP fileset: daily" msgstr "FTP-набор: раз в сутки" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:287 msgid "WWW pages: daily" msgstr "WWW-страницы: раз в сутки" #. type: Title == #: documentation/content/en/articles/hubs/_index.adoc:289 #, no-wrap msgid "Where to Mirror From" msgstr "С какого сервера синхронизироваться" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:294 msgid "" "This is an important issue. So this section will spend some effort to " "explain the backgrounds. We will say this several times: under no " "circumstances should you mirror from `ftp.FreeBSD.org`." msgstr "" "Это важный вопрос, так что мы попытаемся пояснить, откуда берутся ответы. " "Для начала повторим ещё несколько раз: _никогда не синхронизируйтесь с ftp." "FreeBSD.org_." #. type: Title === #: documentation/content/en/articles/hubs/_index.adoc:296 #, no-wrap msgid "A few Words About the Organization" msgstr "Организация системы зеркал" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:307 msgid "" "Mirrors are organized by country. All official mirrors have a DNS entry of " "the form `ftpN.CC.FreeBSD.org`. _CC_ (i.e., country code) is the _top level " "domain_ (TLD) of the country where this mirror is located. _N_ is a number, " "telling that the host would be the _Nth_ mirror in that country. (Same " "applies to `wwwN.CC.FreeBSD.org`, etc.) There are mirrors with no _CC_ " "part. These are the mirror sites that are very well connected and allow a " "large number of concurrent users. `ftp.FreeBSD.org` is actually two " "machines, one currently located in Denmark and the other in the United " "States. It is _NOT_ a master site and should never be used to mirror from. " "Lots of online documentation leads \"interactive\"users to `ftp.FreeBSD.org` " "so automated mirroring systems should find a different machine to mirror " "from." msgstr "" "Зеркала организуются по странам. Имена хостов всех официальных зеркал " "построены по принципу `ftpN.CC.FreeBSD.org`, где _CC_ (country code) - домен " "верхнего уровня страны, где расположено зеркало, _N_ - номер зеркала в " "данной стране. Этот же принцип применим к именам хостов `wwwN.CC.FreeBSD." "org` и т.п. Кроме того, есть зеркала без доменной части, обозначающей " "страну. Все они имеют очень хорошие внешние каналы и обслуживают большое " "число одновременных соединений. Имя `ftp.FreeBSD.org` на самом деле " "указывает на две машины, одна из которых в настоящее время находится в " "Дании, а другая в США. Ни одна из этих машин _НЕ_ является основным сайтом, " "и потому не должна использоваться для синхронизации. Масса документации для " "\"живых\" пользователей указывает на `ftp.FreeBSD.org`, так что " "автоматическим системам ведения зеркал следует выбирать другие источники " "синхронизации." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:317 msgid "" "Additionally there exists a hierarchy of mirrors, which is described in " "terms of __tiers__. The master sites are not referred to but can be " "described as __Tier-0__. Mirrors that mirror from these sites can be " "considered __Tier-1__, mirrors of __Tier-1__-mirrors, are __Tier-2__, etc. " "Official sites are encouraged to be of a low __tier__, but the lower the " "tier the higher the requirements in terms as described in crossref:" "hubs[mirror-requirements, Requirements for FreeBSD Mirrors]. Also access to " "low-tier-mirrors may be restricted, and access to master sites is definitely " "restricted. The __tier__-hierarchy is not reflected by DNS and generally " "not documented anywhere except for the master sites. However, official " "mirrors with low numbers like 1-4, are usually _Tier-1_ (this is just a " "rough hint, and there is no rule)." msgstr "" -"Кроме того, существует иерархия зеркал в терминах их удаленности от центра, " +"Кроме того, существует иерархия зеркал в терминах их удалённости от центра, " "или __слоях__. Основные сайты могут быть описаны как __Зеркала нулевого " "слоя__. Зеркала, синхронизирующиеся по ним, считаются __слоем 1__, следующие " "- _слоем 2_ и т.д. Официальные сайты приглашаются на низкие слои, однако " "следует помнить, что чем меньше номер слоя, тем выше требования к зеркалу, " "как было описано в <>. Помимо того, доступ к зеркалам 1 " "слоя может быть ограничен; безусловно ограничен доступ к основным сайтам. " -"Иерархия _слоев_ не отражается в DNS и, вообще говоря, нигде (кроме мастер-" -"сайтов) не документирована. Тем не менее, официальные зеркала с малыми (1-4, " -"как правило) номерами обычно представляют первый слой. (Это грубая оценка, и " -"ни в коем случае не правило)." +"Иерархия _слоев_ не отражается в DNS и, вообще говоря, нигде (кроме " +"мастер-сайтов) не документирована. Тем не менее, официальные зеркала с " +"малыми (1-4, как правило) номерами обычно представляют первый слой. (Это " +"грубая оценка, и ни в коем случае не правило)." #. type: Title === #: documentation/content/en/articles/hubs/_index.adoc:319 #, no-wrap msgid "Ok, but Where Should I get the Stuff Now?" msgstr "Так откуда же мне синхронизироваться?" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:323 msgid "" "Under no circumstances should you mirror from `ftp.FreeBSD.org`. The short " "answer is: from the site that is closest to you in Internet terms, or gives " "you the fastest access." msgstr "" "Главное - НЕ с `ftp.FreeBSD.org`. Короткий ответ: с зеркала, которое " "расположено недалеко от вас в терминах Интернет, и/или доступ к которому " "наилучший." #. type: Title ==== #: documentation/content/en/articles/hubs/_index.adoc:325 #, no-wrap msgid "I Just Want to Mirror from Somewhere!" msgstr "Я хочу получить копию зеркала хоть откуда-нибудь!" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:330 msgid "" "If you have no special intentions or requirements, the statement in crossref:" "hubs[mirror-where-where, Ok, but Where Should I get the Stuff Now?] " "applies. This means:" msgstr "" "Если у вас нет особых намерений или требований, применимо утверждение в " "crossref:hubs[mirror-where-where, Так откуда же мне синхронизироваться?]. " "Это означает:" #. type: delimited block = 4 #: documentation/content/en/articles/hubs/_index.adoc:334 msgid "" "Check for those which provide fastest access (number of hops, round-trip-" "times) and offer the services you intend to use (like rsync)." msgstr "" "Выберите те из них, с которыми вам работать быстрее всего (меньшее число " "промежуточных узлов и время отклика), и которые предоставляют нужные вам " "сервисы (такие как rsync)." #. type: delimited block = 4 #: documentation/content/en/articles/hubs/_index.adoc:335 msgid "" "Contact the administrators of your chosen site stating your request, and " "asking about their terms and policies." msgstr "" "Свяжитесь с администраторами выбранного сервера, опишите ваши запросы и " "уточните их правила." #. type: delimited block = 4 #: documentation/content/en/articles/hubs/_index.adoc:336 msgid "Set up your mirror as described above." msgstr "Сконфигурируйте ваше зеркало, как описывалось выше." #. type: Title ==== #: documentation/content/en/articles/hubs/_index.adoc:339 #, no-wrap msgid "I am an Official Mirror, What is the Right Site for Me?" msgstr "Я поддерживаю официальное зеркало, какой сайт мне выбрать?" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:345 msgid "" "In general the description in crossref:hubs[mirror-where-simple, I Just Want " "to Mirror from Somewhere!] still applies. Of course you may want to put " "some weight on the fact that your upstream should be of a low tier. There " "are some other considerations about _official_ mirrors that are described in " "crossref:hubs[mirror-official, Official Mirrors]." msgstr "" "В основном, правила, описанные в crossref:hubs[mirror-where-simple, Я хочу " "получить копию зеркала хоть откуда-нибудь!], применимы. Дополнительно можно " "убедиться, что выбранный сайт принадлежит низкому слою. Другие соображения " "относительно _официальных_ зеркал описаны в <>." #. type: Title ==== #: documentation/content/en/articles/hubs/_index.adoc:347 #, no-wrap msgid "I Want to Access the Master Sites!" msgstr "Мне нужен доступ к основным сайтам!" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:354 msgid "" "If you have good reasons and good prerequisites, you may want and get access " "to one of the master sites. Access to these sites is generally restricted, " "and there are special policies for access. If you are already an _official_ " "mirror, this certainly helps you getting access. In any other case make " "sure your country really needs another mirror. If it already has three or " "more, ask the \"zone administrator\" (mailto:hostmaster@CC.FreeBSD." "org[hostmaster@CC.FreeBSD.org]) or {freebsd-hubs} first." msgstr "" "При наличии достаточных причин вы можете получить доступ к одному из " "основных сайтов. Доступ к ним ограничен; существуют специальные правила их " "использования. Наличие у вас статуса _официального_ зеркала, безусловно, " "является хорошим подспорьем. В противном случае убедитесь, что ваша страна " "действительно нуждается ещё в одном зеркале. Если их уже три или более, " "сначала свяжитесь с администратором соответствующей зоны DNS " "(mailto:hostmaster@CC.FreeBSD.org[hostmaster@CC.FreeBSD.org]) или напишите в " "{freebsd-hubs}." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:357 msgid "" "Whoever helped you become, an _official_ should have helped you gain access " "to an appropriate upstream host, either one of the master sites or a " "suitable Tier-1 site. If not, you can send email to mailto:mirror-" "admin@FreeBSD.org[mirror-admin@FreeBSD.org] to request help with that." msgstr "" "Тот, кто помог вам стать _официальным_ зеркалом, должен был помочь вам " "получить доступ к соответствующему вышестоящему хосту — либо к одному из " "основных сайтов, либо к подходящему сайту уровня Tier-1. Если этого не " "произошло, вы можете отправить письмо по адресу mailto:mirror-admin@FreeBSD." "org[mirror-admin@FreeBSD.org], чтобы запросить помощь в этом вопросе." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:359 msgid "There is one master site for the FTP fileset." msgstr "Существует один основной сайт для синхронизации набора файлов FTP." #. type: Title ===== #: documentation/content/en/articles/hubs/_index.adoc:361 #, no-wrap msgid "ftp-master.FreeBSD.org" msgstr "ftp-master.FreeBSD.org" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:364 msgid "This is the master site for the FTP fileset." msgstr "Это основной сервер для синхронизации FTP набора." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:367 msgid "" "`ftp-master.FreeBSD.org` provides rsync access, in addition to FTP. Refer " "to crossref:hubs[mirror-ftp-rsync, Mirroring the FTP Site]." msgstr "" "В дополнение к FTP, `ftp-master.FreeBSD.org` поддерживает доступ по rsync. " "Использование этих протоколов описано в crossref:hubs[mirror-ftp-rsync, " "Mirroring the FTP Site]." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:369 msgid "" "Mirrors are also encouraged to allow rsync access for the FTP contents, " "since they are __Tier-1__-mirrors." msgstr "" "Приветствуется предоставление зеркалами _1 уровня_ доступа к FTP-области по " "протоколу rsync." #. type: Title == #: documentation/content/en/articles/hubs/_index.adoc:371 #, no-wrap msgid "Official Mirrors" msgstr "Официальные зеркала" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:374 msgid "Official mirrors are mirrors that" msgstr "Официальные зеркала обладают следующим свойствами" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:376 msgid "a) have a `FreeBSD.org` DNS entry (usually a CNAME)." msgstr "a) имеют запись в домене `FreeBSD.org` (обычно типа CNAME)." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:377 msgid "" "b) are listed as an official mirror in the FreeBSD documentation (like " "handbook)." msgstr "" "b) присутствуют в списке официальных зеркал в Руководстве по FreeBSD и " "другой документации." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:380 msgid "" "So far to distinguish official mirrors. Official mirrors are not necessarily " "__Tier-1__-mirrors. However you probably will not find a __Tier-1__-mirror, " "that is not also official." msgstr "" "На настоящий момент это все, что отличает их от прочих зеркал. Официальные " "зеркала не обязательно принадлежат к __Первому уровню__, однако, вряд ли " "можно найти зеркало __уровня 1__, не являющееся официальным." #. type: Title === #: documentation/content/en/articles/hubs/_index.adoc:382 #, no-wrap msgid "Special Requirements for Official (tier-1) Mirrors" msgstr "Отдельные требования к официальным зеркалам 1 уровня" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:387 msgid "" "It is not so easy to state requirements for all official mirrors, since the " "project is sort of tolerant here. It is more easy to say, what _official " "tier-1 mirrors_ are required to. All other official mirrors can consider " "this a big __should__." msgstr "" "Описать требования для всех официальных зеркал не так просто, поскольку " "проект FreeBSD достаточно мягок в этом отношении. Несколько проще указать, " "что требуется от __официальных зеркал уровня 1__. Прочие официальные зеркала " "должны рассматривать этот список как __настойчивые пожелания__." #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:389 msgid "Tier-1 mirrors are required to:" msgstr "Зеркала 1 уровня должны:" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:391 msgid "carry the complete fileset" msgstr "поддерживать полный список файлов" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:392 msgid "allow access to other mirror sites" msgstr "предоставлять доступ для других зеркал" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:393 msgid "provide FTP and rsync access" msgstr "обеспечивать доступ по протоколам ftp и rsync" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:396 msgid "" "Furthermore, admins should be subscribed to the {freebsd-hubs}. See extref:" "{handbook}eresources[this link, eresources-mail] for details, how to " "subscribe." msgstr "" "Кроме того, администратор такого зеркала должен быть подписан на {freebsd-" "hubs}. См. extref:{handbook}eresources[здесь, eresources-mail] для " "дополнительной информации о подписке." #. type: delimited block = 4 #: documentation/content/en/articles/hubs/_index.adoc:401 msgid "" "It is _very_ important for a hub administrator, especially Tier-1 hub " "admins, to check the https://www.FreeBSD.org/releng/[release schedule] for " "the next FreeBSD release. This is important because it will tell you when " "the next release is scheduled to come out, and thus giving you time to " "prepare for the big spike of traffic which follows it." msgstr "" "Очень важно для администратора хаба, особенно администраторов хаба уровня " "Tier-1, проверять https://www.FreeBSD.org/releng/[график выпусков] " "следующего релиза FreeBSD. Это важно, потому что это позволит вам узнать, " "когда запланирован выход следующего релиза, и, таким образом, даст вам время " "подготовиться к большому всплеску трафика, который последует за ним." #. type: delimited block = 4 #: documentation/content/en/articles/hubs/_index.adoc:404 msgid "" "It is also important that hub administrators try to keep their mirrors as up-" "to-date as possible (again, even more crucial for Tier-1 mirrors). If " "Mirror1 does not update for a while, lower tier mirrors will begin to mirror " "old data from Mirror1 and thus begins a downward spiral... Keep your mirrors " "up to date!" msgstr "" "Кроме того, важно поддерживать актуальность зеркал (в особенности зеркал " "уровня 1). Если Зеркало1 не синхронизировалось в течение длительного " "времени, то зеркала следующего уровня будут синхронизироваться по устаревшей " "информации и т.д. Поддерживайте актуальность ваших зеркал!" #. type: Title === #: documentation/content/en/articles/hubs/_index.adoc:407 #, no-wrap msgid "How to Become Official Then?" msgstr "Как стать официальным зеркалом?" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:410 msgid "" "Please contact the Cluster Administrators as documented at https://www." "FreeBSD.org/administration/#t-clusteradm." msgstr "" "Обратитесь к администраторам кластера, как указано в документации по адресу " "https://www.FreeBSD.org/administration/#t-clusteradm." #. type: Title == #: documentation/content/en/articles/hubs/_index.adoc:412 #, no-wrap msgid "Some Statistics from Mirror Sites" msgstr "Статистика некоторых зеркал" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:415 msgid "" "Here are links to the stat pages of your favorite mirrors (aka the only ones " "who feel like providing stats)." msgstr "" "Вот ссылки на страницы статистики ваших любимых зеркал (иначе говоря, " "единственных, кто предоставляет такую статистику)." #. type: Title === #: documentation/content/en/articles/hubs/_index.adoc:417 #, no-wrap msgid "FTP Site Statistics" msgstr "Статистика FTP сайтов" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:420 msgid "" "ftp.is.FreeBSD.org - mailto:hostmaster@is.FreeBSD.org[hostmaster@is.FreeBSD." "org] - http://www.rhnet.is/status/draupnir/draupnir.html[ (Bandwidth)] " "http://www.rhnet.is/status/ftp/ftp-notendur.html[(FTP processes)] http://www." "rhnet.is/status/ftp/http-notendur.html[(HTTP processes)]" msgstr "" "ftp.is.FreeBSD.org - mailto:hostmaster@is.FreeBSD.org[hostmaster@is.FreeBSD." "org] - http://www.rhnet.is/status/draupnir/draupnir.html[ (Bandwidth)] " "http://www.rhnet.is/status/ftp/ftp-notendur.html[(FTP processes)] http://www." "rhnet.is/status/ftp/http-notendur.html[(HTTP processes)]" #. type: Plain text #: documentation/content/en/articles/hubs/_index.adoc:420 msgid "" "ftp2.ru.FreeBSD.org - mailto:mirror@macomnet.ru[mirror@macomnet.ru] - http://" "mirror.macomnet.net/mrtg/mirror.macomnet.net_195.128.64.25.html[(Bandwidth)] " "http://mirror.macomnet.net/mrtg/mirror.macomnet.net_proc.html[(HTTP and FTP " "users)]" msgstr "" "ftp2.ru.FreeBSD.org - mailto:mirror@macomnet.ru[mirror@macomnet.ru] - http://" "mirror.macomnet.net/mrtg/mirror.macomnet.net_195.128.64.25.html[(Bandwidth)] " "http://mirror.macomnet.net/mrtg/mirror.macomnet.net_proc.html[(HTTP and FTP " "users)]" diff --git a/documentation/content/ru/articles/linux-emulation/_index.adoc b/documentation/content/ru/articles/linux-emulation/_index.adoc index 481ca6c3f4..f49dd4e57f 100644 --- a/documentation/content/ru/articles/linux-emulation/_index.adoc +++ b/documentation/content/ru/articles/linux-emulation/_index.adoc @@ -1,973 +1,973 @@ --- authors: - author: 'Roman Divacky' email: rdivacky@FreeBSD.org description: 'Техническое описание внутреннего устройства слоя эмуляции Linux в FreeBSD' tags: ["Emulation", "Linuxulator", "kernel", "FreeBSD"] title: 'Эмуляция Linux® в FreeBSD' trademarks: ["freebsd", "ibm", "adobe", "netbsd", "realnetworks", "oracle", "linux", "sun", "general"] --- = Эмуляция Linux(R) в FreeBSD :doctype: article :toc: macro :toclevels: 1 :icons: font :sectnums: :sectnumlevels: 6 :source-highlighter: rouge :experimental: :images-path: articles/linux-emulation/ ifdef::env-beastie[] ifdef::backend-html5[] include::shared/authors.adoc[] include::shared/mirrors.adoc[] include::shared/releases.adoc[] include::shared/attributes/attributes-{{% lang %}}.adoc[] include::shared/{{% lang %}}/teams.adoc[] include::shared/{{% lang %}}/mailing-lists.adoc[] include::shared/{{% lang %}}/urls.adoc[] :imagesdir: ../../../images/{images-path} endif::[] ifdef::backend-pdf,backend-epub3[] include::../../../../shared/asciidoctor.adoc[] endif::[] endif::[] ifndef::env-beastie[] include::../../../../../shared/asciidoctor.adoc[] endif::[] [.abstract-title] Аннотация Эта магистерская диссертация посвящена обновлению слоя эмуляции Linux(R) (так называемого _Linuxulator_). Задача состояла в обновлении слоя для соответствия функциональности Linux(R) 2.6. В качестве эталонной реализации было выбрано ядро Linux(R) 2.6.16. Концепция основана на реализации NetBSD. Большая часть работы была выполнена летом 2006 года в рамках программы Google Summer of Code для студентов. Основное внимание уделялось добавлению поддержки _NPTL_ (новой библиотеки потоков POSIX(R)) в слой эмуляции, включая _TLS_ (локальное хранилище потоков), _фьютексы (futex)_ (быстрые мьютексы в пользовательском пространстве), _PID mangling_ и некоторые другие второстепенные аспекты. В процессе было выявлено и исправлено множество мелких проблем. Моя работа была интегрирована в основной репозиторий исходного кода FreeBSD и войдет в предстоящий релиз 7.0R. Мы, команда разработчиков эмуляции, работаем над тем, чтобы сделать эмуляцию Linux(R) 2.6 стандартным слоем эмуляции в FreeBSD. ''' toc::[] [[intro]] == Введение В последние несколько лет операционные системы с открытым исходным кодом на основе UNIX(R) начали широко использоваться на серверных и клиентских машинах. Среди этих операционных систем я хотел бы выделить две: FreeBSD — за наследие BSD, проверенную временем кодобазу и множество интересных возможностей, и Linux(R) — за широкую пользовательскую базу, активное сообщество разработчиков и поддержку крупных компаний. FreeBSD чаще используется на серверных машинах, выполняющих сложные сетевые задачи, и реже — на настольных компьютерах обычных пользователей. В то время как Linux(R) также применяется на серверах, он гораздо популярнее среди домашних пользователей. Это приводит к ситуации, когда для Linux(R) доступно множество проприетарных программ, которые не поддерживают FreeBSD. Естественно, возникает необходимость в возможности запуска Linux(R) бинарников в системе FreeBSD, и именно этому посвящена данная работа: эмуляции ядра Linux(R) в операционной системе FreeBSD. Летом 2006 года компания Google Inc. спонсировала проект, направленный на расширение слоя эмуляции Linux(R) (так называемого Linuxulator) в FreeBSD для включения возможностей Linux(R) 2.6. Данная диссертация написана в рамках этого проекта. [[inside]] == Взгляд изнутри... В этом разделе мы рассмотрим каждую из рассматриваемых операционных систем. Как они работают с системными вызовами, фреймами прерываний и другими низкоуровневыми аспектами. Также мы опишем, как они интерпретируют общие примитивы UNIX(R), такие как PID, потоки и т. д. В третьем подразделе мы поговорим о том, как в целом может быть реализована эмуляция UNIX(R) на UNIX(R). [[what-is-unix]] === Что такое UNIX(R) UNIX(R) — это операционная система с долгой историей, которая повлияла почти на все остальные операционные системы, используемые в настоящее время. Начиная с 1960-х годов, её разработка продолжается и по сей день (хотя в разных проектах). Вскоре развитие UNIX(R) разделилось на два основных направления: семейства BSD и System III/V. Они взаимно влияли друг на друга, формируя общий стандарт UNIX(R). Среди вклада, возникшего в BSD, можно назвать виртуальную память, сетевой стек TCP/IP, FFS и многие другие. Ветка System V внесла свой вклад в примитивы межпроцессного взаимодействия SysV, копирование при записи и т. д. Самого UNIX(R) больше не существует, но его идеи были использованы многими другими операционными системами по всему миру, образовав так называемые UNIX(R)-подобные операционные системы. В наши дни наиболее влиятельными из них являются Linux(R), Solaris и, возможно (в некоторой степени), FreeBSD. Существуют корпоративные производные UNIX(R) (AIX, HP-UX и т. д.), но они всё больше мигрируют на упомянутые системы. Давайте подведём итог типичным характеристикам UNIX(R). [[tech-details]] === Технические детали Каждая запущенная программа представляет собой процесс, который отражает состояние вычислений. Выполняющийся процесс разделяется между пространством ядра и пользовательским пространством. Некоторые операции могут выполняться только из пространства ядра (например, работа с оборудованием), но процесс должен проводить большую часть своего времени в пользовательском пространстве. Ядро — это место, где происходит управление процессами, оборудованием и низкоуровневыми деталями. Ядро предоставляет стандартный унифицированный UNIX(R) API для пользовательского пространства. Наиболее важные из них рассмотрены ниже. [[kern-proc-comm]] ==== Обмен данными между ядром и пользовательским процессом Общий API UNIX(R) определяет системный вызов как способ передачи команд из пользовательского процесса ядру. Наиболее распространённая реализация использует либо прерывание, либо специализированную инструкцию (например, инструкции `SYSENTER`/`SYSCALL` для ia32). Системные вызовы определяются по номеру. Например, в FreeBSD системный вызов номер 85 — это man:swapon[2], а номер 132 — man:mkfifo[2]. Некоторые системные вызовы требуют параметров, которые передаются из пользовательского пространства в пространство ядра различными способами (зависит от реализации). Системные вызовы являются синхронными. Еще один возможный способ взаимодействия — использование _прерывания_. Прерывания происходят асинхронно после возникновения определённого события (деление на ноль, ошибка страницы и т.д.). Прерывание может быть прозрачным для процесса (ошибка страницы) или привести к реакции, например, отправке _сигнала_ (деление на ноль). [[proc-proc-comm]] ==== Обмен данными между процессами Существуют другие API (System V IPC, разделяемая память и т.д.), но наиболее важным API являются сигналы. Сигналы отправляются процессами или ядром и принимаются процессами. Некоторые сигналы могут быть проигнорированы или обработаны пользовательской процедурой, другие приводят к предопределённому действию, которое нельзя изменить или игнорировать. [[proc-mgmt]] ==== Управление процессами Процессы ядра обрабатываются первыми в системе (так называемый init). Каждый запущенный процесс может создать свою идентичную копию, используя системный вызов man:fork[2]. Были введены некоторые немного изменённые версии этого системного вызова, но базовая семантика остаётся той же. Каждый запущенный процесс может превратиться в другой процесс, используя системный вызов man:exec[3]. Были введены некоторые модификации этого системного вызова, но все они служат одной и той же базовой цели. Процессы завершают своё существование, вызывая системный вызов man:exit[2]. Каждый процесс идентифицируется уникальным номером, называемым PID. У каждого процесса есть определённый родитель (идентифицируемый его PID). [[thread-mgmt]] ==== Управление потоками Традиционный UNIX(R) не определяет никакого API или реализации для потоков, в то время как POSIX(R) определяет свой API для потоков, но реализация остаётся неопределённой. Традиционно существовало два способа реализации потоков: обработка их как отдельных процессов (потоки 1:1) или обёртывание всей группы потоков в один процесс с управлением потоками в пользовательском пространстве (потоки 1:N). Сравнение основных особенностей каждого подхода: Потоки 1:1 - тяжеловесные потоки - планирование не может быть изменено пользователем (частично смягчено благодаря POSIX(R) API) + нет необходимости в обёртке системных вызовов + может использовать несколько процессоров Потоки 1:N + легковесные потоки + планирование может быть легко изменено пользователем - Системные вызовы должны быть обернуты - не может использовать более одного CPU [[what-is-freebsd]] === Что такое FreeBSD? Проект FreeBSD — одна из старейших операционных систем с открытым исходным кодом, доступных для повседневного использования. Она является прямым потомком оригинальной UNIX(R), поэтому можно утверждать, что это настоящая UNIX(R), хотя проблемы с лицензированием не позволяют этого сделать. Начало проекта относится к началу 1990-х годов, когда группа пользователей BSD создала набор исправлений для операционной системы 386BSD. На основе этого набора возникла новая операционная система под названием FreeBSD, получившая своё имя благодаря либеральной лицензии. Другая группа создала операционную систему NetBSD с другими целями. Мы сосредоточимся на FreeBSD. FreeBSD — это современная операционная система на основе UNIX(R), обладающая всеми возможностями UNIX(R). Вытесняющая многозадачность, многопользовательские функции, сетевые возможности TCP/IP, защита памяти, поддержка симметричной многопроцессорности, виртуальная память с объединёнными VM и кэшем буфера — всё это присутствует. Одной из интересных и чрезвычайно полезных особенностей является возможность эмуляции других UNIX(R)-подобных операционных систем. По состоянию на декабрь 2006 года и разработку 7-CURRENT поддерживаются следующие функции эмуляции: * Совместимость FreeBSD/i386 на FreeBSD/amd64 * FreeBSD/i386 эмуляция на FreeBSD/ia64 * Эмуляция Linux(R) операционной системы Linux(R) на FreeBSD * NDIS-эмуляция интерфейса сетевых драйверов Windows * NetBSD-эмуляция операционной системы NetBSD * Поддержка PECoff для исполняемых файлов FreeBSD в формате PECoff * Эмуляция SVR4 System V revision 4 UNIX(R) Активно разрабатываемые эмуляции — это слой Linux(R) и различные слои FreeBSD-on-FreeBSD. Остальные в настоящее время не должны работать корректно или быть пригодными к использованию. [[freebsd-tech-details]] ==== Технические детали FreeBSD — это традиционный вариант UNIX(R) в смысле разделения выполнения процессов на две части: выполнение в пространстве ядра и выполнение в пространстве пользователя. Существует два типа входа процесса в ядро: системный вызов (syscall) и ловушка (trap). Возврат только один. В последующих разделах мы опишем три входа/выхода в/из ядра. Всё описание относится к архитектуре i386, так как Linuxulator существует только там, но концепция схожа на других архитектурах. Информация была взята из [1] и исходного кода. [[freebsd-sys-entries]] ===== Системные записи В FreeBSD существует абстракция, называемая загрузчиком классов исполнения, которая является прослойкой в системном вызове man:execve[2]. Она использует структуру `sysentvec`, описывающую ABI исполняемого файла. Эта структура содержит такие элементы, как таблицу преобразования errno, таблицу преобразования сигналов, различные функции для обработки системных вызовов (исправление стека, создание дампов памяти и т.д.). Каждый ABI, который ядро FreeBSD поддерживает, должен определять эту структуру, так как она используется в дальнейшем в коде обработки системных вызовов и в некоторых других местах. Системные вызовы обрабатываются обработчиками прерываний, где можно одновременно получить доступ как к пространству ядра, так и к пользовательскому пространству. [[freebsd-syscalls]] ===== Системные вызовы Системные вызовы в FreeBSD выполняются путем прерывания `0x80` с установленным в регистре `%eax` номером нужного системного вызова и аргументами, переданными через стек. Когда процесс вызывает прерывание `0x80`, срабатывает обработчик системного вызова `int0x80` (определённый в [.filename]#sys/i386/i386/exception.s#), который подготавливает аргументы (т.е. копирует их в стек) для вызова функции на языке C man:syscall[2] (определённой в [.filename]#sys/i386/i386/trap.c#), обрабатывающей переданный фрейм прерывания. Обработка включает подготовку системного вызова (в зависимости от записи `sysvec`), определение разрядности системного вызова (32-битный или 64-битный, что влияет на размер параметров), после чего параметры копируются, включая сам системный вызов. Затем выполняется фактическая функция системного вызова с обработкой кода возврата (особые случаи для ошибок `ERESTART` и `EJUSTRETURN`). В завершение планируется вызов `userret()`, возвращающий процесс в пользовательское пространство. Параметры для фактического обработчика системного вызова передаются в виде аргументов `struct thread *td`, `struct syscall args *`, где второй параметр является указателем на скопированную структуру параметров. [[freebsd-traps]] ===== Ловушки (trap) Обработка ловушек в FreeBSD аналогична обработке системных вызовов. При возникновении ловушки вызывается обработчик на ассемблере. Он выбирается между `alltraps`, `alltraps` с сохранением регистров или `calltrap` в зависимости от типа ловушки. Этот обработчик подготавливает аргументы для вызова функции на языке C `trap()` (определена в [.filename]#sys/i386/i386/trap.c#), которая затем обрабатывает произошедшую ловушку. После обработки она может отправить сигнал процессу и/или вернуться в пользовательское пространство с помощью `userret()`. [[freebsd-exits]] ===== Выходы Выход из ядра в пользовательское пространство происходит с использованием ассемблерной процедуры `doreti`, независимо от того, было ли ядро вызвано через ловушку или через системный вызов. Это восстанавливает состояние программы из стека и возвращает управление в пользовательское пространство. [[freebsd-unix-primitives]] ===== Примитивы UNIX(R) Операционная система FreeBSD придерживается традиционной схемы UNIX(R), где каждый процесс имеет уникальный идентификационный номер, так называемый _PID_ (Идентификатор Процесса). Номера PID выделяются либо линейно, либо случайным образом в диапазоне от `0` до `PID_MAX`. Распределение номеров PID осуществляется с помощью линейного поиска в пространстве PID. Каждый поток в процессе получает тот же номер PID в результате вызова man:getpid[2]. В настоящее время в FreeBSD существует два способа реализации потоков. Первый способ — это M:N потоки, за которым следует модель потоков 1:1. По умолчанию используется библиотека M:N (`libpthread`), но во время выполнения можно переключиться на потоки 1:1 (`libthr`). Планируется в ближайшее время перейти на библиотеку 1:1 по умолчанию. Хотя обе библиотеки используют одни и те же примитивы ядра, доступ к ним осуществляется через разные API. Библиотека M:N использует семейство системных вызовов `kse_*`, тогда как библиотека 1:1 использует семейство `thr_*`. Из-за этого отсутствует общая концепция идентификатора потока, разделяемая между ядром и пользовательским пространством. Конечно, обе библиотеки реализуют API идентификатора потока pthread. У каждого потока ядра (как описано в `struct thread`) есть идентификатор td tid, но он недоступен напрямую из пользовательского пространства и служит исключительно нуждам ядра. Он также используется в библиотеке потоков 1:1 в качестве идентификатора потока pthread, но обработка этого идентификатора внутренняя для библиотеки и не может быть использована напрямую. Как упоминалось ранее, в FreeBSD существуют две реализации потоков. Библиотека M:N разделяет работу между пространством ядра и пользовательским пространством. Поток — это сущность, которая планируется в ядре, но может представлять различное количество пользовательских потоков. M пользовательских потоков отображаются на N потоков ядра, что позволяет экономить ресурсы, сохраняя при этом возможность использовать преимущества многопроцессорного параллелизма. Дополнительную информацию о реализации можно получить из man-страницы или [1]. Библиотека 1:1 напрямую отображает пользовательский поток на поток ядра, что значительно упрощает схему. Ни одна из этих реализаций не включает механизм справедливости (такой механизм был реализован, но недавно удалён, поскольку вызывал серьёзное замедление и усложнял работу с кодом). [[what-is-linux]] === Что такое Linux(R) Linux(R) — это UNIX(R)-подобное ядро, изначально разработанное Линусом Торвальдсом, а сейчас развиваемое множеством программистов по всему миру. От своих скромных начал до сегодняшнего дня, при широкой поддержке таких компаний, как IBM или Google, Linux(R) ассоциируется с быстрым темпом разработки, полной поддержкой оборудования и моделью организации по принципу "доброжелательного диктатора". Разработка Linux(R) началась в 1991 году как любительский проект в Университете Хельсинки, Финляндия. С тех пор она приобрела все черты современной ОС, подобной UNIX(R): многопроцессорность, поддержка многопользовательского режима, виртуальная память, сетевое взаимодействие — в общем, всё необходимое. Также присутствуют высокоуровневые функции, такие как виртуализация и т. д. В 2006 году Linux(R), похоже, был наиболее широко используемой открытой операционной системой с поддержкой независимых поставщиков программного обеспечения, таких как Oracle, RealNetworks, Adobe и других. Большая часть коммерческого программного обеспечения, распространяемого для Linux(R), доступна только в бинарном виде, поэтому перекомпиляция для других операционных систем невозможна. Большая часть разработки Linux(R) происходит в системе контроля версий Git. Git — это распределённая система, поэтому нет централизованного источника кода Linux(R), но некоторые ветви считаются основными и официальными. Схема нумерации версий, используемая в Linux(R), состоит из четырёх чисел: A.B.C.D. В настоящее время разработка ведётся в ветке 2.6.C.D, где C обозначает мажорную версию, в которую добавляются или изменяются функции, а D — минорную версию, предназначенную только для исправления ошибок. Дополнительную информацию можно получить из [3]. [[linux-tech-details]] ==== Технические детали Linux(R) следует традиционной схеме UNIX(R), разделяя выполнение процесса на две части: ядро и пользовательское пространство. Ядро может быть вызвано двумя способами: через ловушку (trap) или через системный вызов. Возврат осуществляется только одним способом. Далее описание относится к Linux(R) 2.6 на архитектуре i386(TM). Эта информация взята из [2]. [[linux-syscalls]] ===== Системные вызовы Системные вызовы в Linux(R) выполняются (в пользовательском пространстве) с использованием макросов `syscallX`, где X заменяется числом, представляющим количество параметров данного системного вызова. Этот макрос преобразуется в код, который загружает регистр `%eax` номером системного вызова и выполняет прерывание `0x80`. После этого вызывается возврат из системного вызова, который преобразует отрицательные значения возврата в положительные значения `errno` и устанавливает `res` в `-1` в случае ошибки. При вызове прерывания `0x80` процесс переходит в ядро в обработчик ловушки системного вызова. Эта процедура сохраняет все регистры в стеке и вызывает выбранную точку входа системного вызова. Обратите внимание, что соглашение о вызовах Linux(R) предполагает передачу параметров системного вызова через регистры, как показано здесь: . параметр -> `%ebx` . параметр -> `%ecx` . параметр -> `%edx` . параметр -> `%esi` . параметр -> `%edi` . параметр -> `%ebp` Существуют некоторые исключения из этого правила, где Linux(R) использует другие соглашения о вызовах (наиболее примечателен системный вызов `clone`). [[linux-traps]] ===== Ловушки (trap) Обработчики ловушек представлены в файле [.filename]#arch/i386/kernel/traps.c#, а большинство этих обработчиков находятся в [.filename]#arch/i386/kernel/entry.S#, где происходит обработка ловушек. [[linux-exits]] ===== Выходы Возврат из системного вызова обрабатывается функцией `syscall man:exit[3]`, которая проверяет, есть ли у процесса незавершённые задачи, затем проверяет, использовались ли селекторы, предоставленные пользователем. Если это произошло, применяется исправление стека, и, наконец, регистры восстанавливаются из стека, а процесс возвращается в пользовательское пространство. [[linux-unix-primitives]] ===== Примитивы UNIX(R) В версии 2.6 операционная система Linux(R) переопределила некоторые традиционные примитивы UNIX(R), в частности PID, TID и поток. PID определяется не как уникальный для каждого процесса, поэтому для некоторых процессов (потоков) man:getppid[2] возвращает одинаковое значение. Уникальная идентификация процесса обеспечивается TID. Это связано с тем, что _NPTL_ (New POSIX(R) Thread Library) определяет потоки как обычные процессы (так называемая модель 1:1). Создание нового процесса в Linux(R) 2.6 происходит с использованием системного вызова `clone` (варианты fork перереализованы с его использованием). Этот системный вызов clone определяет набор флагов, которые влияют на поведение процесса клонирования в отношении реализации потоков. Семантика немного размыта, так как нет единого флага, указывающего системному вызову создать поток. Реализованные флаги клонирования: * `CLONE_VM` - процессы разделяют общее адресное пространство * `CLONE_FS` — совместно использовать umask, текущий рабочий каталог и пространство имён * `CLONE_FILES` - совместно использовать открытые файлы * `CLONE_SIGHAND` - разделять обработчики сигналов и заблокированные сигналы * `CLONE_PARENT` - использовать один процесс к качестве родительского * `CLONE_THREAD` — быть потоком (дальнейшие пояснения ниже) * `CLONE_NEWNS` - новое пространство имен * `CLONE_SYSVSEM` - совместное использование структур отмены SysV * `CLONE_SETTLS` - настройка TLS по указанному адресу * `CLONE_PARENT_SETTID` - установить TID в родителе * `CLONE_CHILD_CLEARTID` - очистить TID в дочернем процессе * `CLONE_CHILD_SETTID` - установить TID в дочернем процессе `CLONE_PARENT` устанавливает реального родителя в родителя вызывающего процесса. Это полезно для потоков, потому что если поток A создаёт поток B, мы хотим, чтобы поток B был привязан к родителю всей группы потоков. `CLONE_THREAD` делает то же самое, что `CLONE_PARENT`, `CLONE_VM` и `CLONE_SIGHAND`, перезаписывает PID, чтобы он совпадал с PID вызывающего процесса, устанавливает сигнал завершения в "нет" и входит в группу потоков. `CLONE_SETTLS` настраивает записи GDT для обработки TLS. Набор флагов `CLONE_*_*TID` устанавливает/сбрасывает предоставленный пользователем адрес в TID или 0. Как видно, `CLONE_THREAD` выполняет большую часть работы и не очень хорошо вписывается в схему. Первоначальный замысел неясен (даже для авторов, согласно комментариям в коде), но я думаю, изначально был один флаг для потоков, который затем был разделён на множество других флагов, но это разделение так и не было завершено. Также непонятно, для чего нужно это разделение, так как glibc не использует его, и только ручное использование clone позволяет программисту получить доступ к этим возможностям. Для непоточных программ PID и TID совпадают. Для поточных программ первый поток имеет одинаковые PID и TID, а каждый созданный поток разделяет тот же PID и получает уникальный TID (поскольку передаётся `CLONE_THREAD`), также родительский процесс общий для всех процессов, образующих эту поточную программу. Код, реализующий man:pthread_create[3] в NPTL, определяет флаги clone следующим образом: [.programlisting] .... int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_SYSVSEM #if __ASSUME_NO_CLONE_DETACHED == 0 | CLONE_DETACHED #endif | 0); .... `CLONE_SIGNAL` определен как [.programlisting] .... #define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD) .... последний 0 означает, что сигнал не отправляется при завершении любого из потоков. [[what-is-emu]] === Что такое эмуляция Согласно словарному определению, эмуляция — это способность программы или устройства имитировать другую программу или устройство. Это достигается за счёт предоставления той же реакции на заданный стимул, что и у эмулируемого объекта. На практике в мире программного обеспечения в основном встречаются три типа эмуляции — программа, используемая для эмуляции машины (QEMU, различные эмуляторы игровых консолей и т.д.), программная эмуляция аппаратного обеспечения (эмуляторы OpenGL, эмуляция блоков плавающей запятой и т.д.) и эмуляция операционной системы (либо в ядре операционной системы, либо в виде программы пользовательского пространства). Эмуляция обычно используется в тех случаях, когда применение оригинального компонента невозможно или нецелесообразно. Например, может возникнуть необходимость использовать программу, разработанную для другой операционной системы. В такой ситуации на помощь приходит эмуляция. Иногда эмуляция — единственный возможный вариант, например, когда необходимое аппаратное устройство ещё не существует или уже не выпускается. Такое часто происходит при переносе операционной системы на новую (ещё не существующую) платформу. Иногда эмуляция просто экономически выгоднее. С точки зрения реализации, существует два основных подхода к эмуляции. Вы можете либо эмулировать всё целиком — принимать возможные входные данные исходного объекта, поддерживать внутреннее состояние и выдавать корректные выходные данные на основе состояния и/или входных данных. Такой вид эмуляции не требует каких-либо специальных условий и, в принципе, может быть реализован где угодно для любого устройства/программы. Недостаток в том, что реализация такой эмуляции довольно сложна, трудоёмка и подвержена ошибкам. В некоторых случаях можно использовать более простой подход. Представьте, что вы хотите эмулировать принтер, печатающий слева направо, на принтере, который печатает справа налево. Очевидно, что нет необходимости в сложном слое эмуляции — достаточно просто перевернуть печатаемый текст. Иногда эмулирующая среда очень похожа на эмулируемую, и тогда достаточно тонкого слоя преобразования для обеспечения полностью рабочей эмуляции! Как видите, такой подход гораздо менее требователен к реализации, а значит, менее трудоёмок и подвержен ошибкам, чем предыдущий. Однако необходимое условие — две среды должны быть достаточно схожи. Третий подход сочетает в себе два предыдущих. Чаще всего объекты не предоставляют одинаковые возможности, поэтому в случае эмуляции более мощного объекта на менее мощном приходится эмулировать отсутствующие функции с помощью полной эмуляции, описанной выше. Эта магистерская диссертация посвящена эмуляции UNIX(R) на UNIX(R), что является именно тем случаем, когда достаточно тонкого слоя трансляции для обеспечения полной эмуляции. API UNIX(R) состоит из набора системных вызовов, которые обычно самодостаточны и не влияют на глобальное состояние ядра. Существует несколько системных вызовов, которые влияют на внутреннее состояние, но это можно решить, предоставив некоторые структуры, поддерживающие дополнительное состояние. Эмуляция не бывает идеальной, и в эмуляторах часто чего-то не хватает, но обычно это не вызывает серьёзных проблем. Представьте эмулятор игровой приставки, который эмулирует всё, кроме звука. Без сомнения, игры остаются играбельными, и эмулятором можно пользоваться. Возможно, это не так комфортно, как оригинальная приставка, но это приемлемый компромисс между ценой и удобством. То же самое касается UNIX(R) API. Большинство программ могут работать с очень ограниченным набором системных вызовов. Эти вызовы, как правило, являются самыми старыми (man:read[2]/man:write[2], семейство man:fork[2], обработка man:signal[3], man:exit[3], API man:socket[2]), поэтому их легко эмулировать, поскольку их семантика одинакова во всех современных UNIX(R)-подобных системах. [[freebsd-emulation]] == Эмуляция === Как работает эмуляция в FreeBSD Как упоминалось ранее, FreeBSD поддерживает выполнение бинарных файлов из нескольких других UNIX(R)-подобных систем. Это возможно благодаря наличию в FreeBSD абстракции, называемой загрузчик классов исполнения. Он интегрируется в системный вызов man:execve[2], поэтому когда man:execve[2] собирается выполнить бинарный файл, он анализирует его тип. В FreeBSD существуют два основных типа исполняемых файлов. Текстовые скрипты, подобные shell-скриптам, которые идентифицируются по первым двум символам `#!`, и обычные (как правило, _ELF_) бинарные файлы, представляющие собой скомпилированные исполняемые объекты. Подавляющее большинство (можно сказать, все) исполняемых файлов в FreeBSD относятся к типу ELF. Файлы ELF содержат заголовок, который определяет ABI операционной системы для данного ELF-файла. Считывая эту информацию, операционная система может точно определить, к какому типу относится данный исполняемый файл. Каждый ABI ОС должен быть зарегистрирован в ядре FreeBSD. Это относится и к родному ABI ОС FreeBSD. Таким образом, когда man:execve[2] выполняет двоичный файл, он перебирает список зарегистрированных API, и когда находит подходящий, начинает использовать информацию, содержащуюся в описании ABI ОС (его таблицу системных вызовов, таблицу преобразования `errno` и т.д.). Таким образом, каждый раз, когда процесс вызывает системный вызов, он использует свой собственный набор системных вызовов вместо какого-либо глобального. Это обеспечивает очень элегантный и простой способ поддержки выполнения различных двоичных форматов. Природа эмуляции различных ОС (а также некоторых других подсистем) привела разработчиков к внедрению механизма обработчиков событий. В ядре существует множество мест, где вызывается список обработчиков событий. Каждая подсистема может зарегистрировать обработчик событий, и они вызываются соответствующим образом. Например, при завершении процесса вызывается обработчик, который может выполнить необходимую очистку для подсистемы. Те простые средства предоставляют практически всё необходимое для инфраструктуры эмуляции, и, по сути, это единственное, что требуется для реализации слоя эмуляции Linux(R). [[freebsd-common-primitives]] === Общие примитивы в ядре FreeBSD Для работы слоев эмуляции требуется некоторая поддержка со стороны операционной системы. Я расскажу о некоторых поддерживаемых примитивах в операционной системе FreeBSD. [[freebsd-locking-primitives]] ==== Примитивы синхронизации Добавил: `{attilio}` Примитивы синхронизации FreeBSD основаны на идее предоставления достаточно большого количества различных примитивов таким образом, чтобы для каждой конкретной подходящей ситуации можно было использовать наилучший. На высоком уровне можно выделить три вида примитивов синхронизации в ядре FreeBSD: * атомарные операции и барьеры памяти * блокировки * барьеры планирования Ниже приведены описания для 3 семейств. Для каждой блокировки рекомендуется ознакомиться с соответствующей справочной страницей (где это возможно), чтобы получить более подробные объяснения. [[freebsd-atomic-op]] ===== Атомарные операции и барьеры памяти Атомарные операции реализуются через набор функций, выполняющих простые арифметические действия над операндами в памяти атомарным образом по отношению к внешним событиям (прерываниям, вытеснению и т. д.). Атомарные операции могут гарантировать атомарность только для небольших типов данных (порядка величины типа `.long` в архитектуре C), поэтому их следует редко использовать напрямую в конечном коде, разве что для очень простых операций (например, установки флага в битовой карте). На самом деле довольно просто и часто можно допустить семантическую ошибку, полагаясь только на атомарные операции (обычно называемые lock-less). Ядро FreeBSD предоставляет способ выполнения атомарных операций в сочетании с барьерами памяти. Барьеры памяти гарантируют, что атомарная операция произойдет в определённом порядке относительно других обращений к памяти. Например, если нам нужно, чтобы атомарная операция выполнилась только после завершения всех ожидающих операций записи (с точки зрения переупорядочивания буферов инструкций), нам необходимо явно использовать барьер памяти вместе с этой атомарной операцией. Таким образом, легко понять, почему барьеры памяти играют ключевую роль в построении высокоуровневых блокировок (таких как refcounts, мьютексы и т. д.). Для подробного объяснения атомарных операций обратитесь к man:atomic[9]. Однако важно отметить, что атомарные операции (и барьеры памяти тоже) в идеале должны использоваться только для построения фронтенд-блокировок (например, мьютексов). [[freebsd-refcounts]] ===== Счетчики ссылок (refcount) Счетчики ссылок (refcounts) — это интерфейсы для работы с подсчетом ссылок. Они реализованы с использованием атомарных операций и предназначены для случаев, когда счетчик ссылок — это единственное, что требует защиты, поэтому даже такие механизмы, как спин-мьютекс, не рекомендуются. Использование интерфейса refcount для структур, где уже применяется мьютекс, часто является ошибкой, так как, вероятно, следует защитить счетчик ссылок в рамках уже существующих защищенных участков кода. В настоящее время man-страница, посвященная refcount, отсутствует; для обзора существующего API обратитесь к [.filename]#sys/refcount.h#. [[freebsd-locks]] ===== Блокировки Ядро FreeBSD имеет множество классов блокировок. Каждая блокировка определяется некоторыми уникальными свойствами, но, вероятно, наиболее важным является событие, связанное с конкурирующими владельцами (или, другими словами, поведение потоков, неспособных захватить блокировку). Схема блокировок FreeBSD предлагает три различных поведения для конкурирующих потоков: . вращающиеся . блокирующие . спящие [NOTE] ==== номера приведены не случайно ==== [[freebsd-spinlocks]] ===== Вращающиеся блокировки Спин-блокировки позволяют ожидающим потокам продолжать работу (вращаться), пока они не смогут захватить блокировку. Важным аспектом является ситуация, когда поток соревнуется за спин-блокировку и не вытесняется. Поскольку ядро FreeBSD является вытесняющим, это подвергает спин-блокировки риску взаимоблокировок, которые можно устранить только отключением прерываний на время их удержания. По этой и другим причинам (таким как отсутствие поддержки распространения приоритетов, неэффективность схем балансировки нагрузки между CPU и т.д.), спин-блокировки предназначены для защиты очень небольших участков кода или, в идеале, не должны использоваться вовсе, если это не требуется явно (об этом далее). [[freebsd-blocking]] ===== Блокирующие Блокирующие блокировки позволяют ожидающим потокам быть выгруженными и заблокированными до тех пор, пока владелец блокировки не освободит её и не разбудит один или несколько конкурентов. Чтобы избежать проблем с голоданием, блокирующие блокировки передают приоритет от ожидающих к владельцу. Блокирующие блокировки должны быть реализованы через интерфейс турникета и предназначены для наиболее частого использования в ядре, если нет особых условий. [[freebsd-sleeping]] ===== Спящие Спящие блокировки (с ожиданием) позволяют ожидающим потокам быть вытесненными и заснуть до тех пор, пока держатель блокировки не освободит её и не разбудит один или несколько ожидающих. Поскольку блокировки с ожиданием предназначены для защиты больших участков кода и обработки асинхронных событий, они не поддерживают распространение приоритетов. Они должны быть реализованы через интерфейс man:sleepqueue[9]. Порядок захвата блокировок очень важен, не только из-за возможности взаимоблокировки при обратном порядке захвата, но и потому, что захват блокировок должен следовать определённым правилам, связанным с их природой. Если взглянуть на таблицу выше, практическое правило заключается в том, что если поток удерживает блокировку уровня n (где уровень — это число, указанное рядом с типом блокировки), ему запрещено захватывать блокировки более высоких уровней, так как это нарушит заданную семантику пути. Например, если поток удерживает блокирующую блокировку (уровень 2), ему разрешено захватывать спин-блокировку (уровень 1), но не спящую блокировку (уровень 3), поскольку блокирующие блокировки предназначены для защиты более коротких путей, чем спящие блокировки (однако эти правила не касаются атомарных операций или барьеров планирования). Вот список блокировок с соответствующими типами поведения: * spin mutex – вращающийся режим – man:mutex[9] * sleep mutex – блокирующий режим – man:mutex[9] * pool mutex – блокирующий режим – man:mtx[pool] * Семейство функций sleep – спящий режим – man:sleep[9] pause tsleep msleep msleep_spin msleep_rw msleep_sx * condvar – спящий режим – man:condvar[9] * rwlock – блокирующий режим – man:rwlock[9] * sxlock – спящий режим – man:sx[9] * lockmgr – спящий режим – man:lockmgr[9] * семафоры – спящий режим – man:sema[9] Среди этих блокировок только мьютексы, sxlock, rwlock и lockmgr предназначены для обработки рекурсии, но в настоящее время рекурсия поддерживается только мьютексами и lockmgr. [[freebsd-scheduling]] ===== Барьеры планирования Барьеры планирования предназначены для управления планированием потоков. Они в основном состоят из трёх различных заглушек: * критические секции (и вытеснение) * sched_bind * sched_pin Как правило, их следует использовать только в определённом контексте, и даже если они часто могут заменять блокировки, их следует избегать, поскольку они не позволяют диагностировать простые потенциальные проблемы с помощью инструментов отладки блокировок (например, man:witness[4]). [[freebsd-critical]] ===== Критические секции В ядре FreeBSD была реализована вытесняющая многозадачность в основном для работы с потоками обработки прерываний. Фактически, чтобы избежать высокой задержки прерываний, потоки с приоритетом разделения времени могут быть вытеснены потоками обработки прерываний (таким образом, им не нужно ждать планирования, как это предусмотрено в обычном случае). Однако вытеснение также вводит новые точки гонки, которые необходимо обрабатывать. Часто для борьбы с вытеснением проще всего полностью отключить его. Критическая секция определяет участок кода (ограниченный парой функций man:critical_enter[9] и man:critical_exit[9]), где гарантируется отсутствие вытеснения (пока защищённый код не будет полностью выполнен). Это часто может эффективно заменить блокировку, но должно использоваться осторожно, чтобы не потерять все преимущества, которые даёт вытеснение. [[freebsd-schedpin]] ===== sched_pin/sched_unpin Еще один способ работы с вытеснением — это интерфейс `sched_pin()`. Если участок кода заключен между функциями `sched_pin()` и `sched_unpin()`, гарантируется, что соответствующий поток, даже если он может быть вытеснен, всегда будет выполняться на том же CPU. Закрепление очень эффективно в частном случае, когда нам необходимо обращаться к данным, привязанным к определённым CPU, и мы предполагаем, что другие потоки не изменят эти данные. Последнее условие делает критическую секцию избыточно строгим условием для нашего кода. [[freebsd-schedbind]] ===== sched_bind/sched_unbind `sched_bind` — это API, используемый для привязки потока к определённому CPU на всё время выполнения кода, пока вызов функции `sched_unbind` не отменит эту привязку. Эта функция играет ключевую роль в ситуациях, когда нельзя доверять текущему состоянию CPU (например, на самых ранних этапах загрузки), так как требуется избежать миграции потока на неактивные CPU. Поскольку `sched_bind` и `sched_unbind` работают с внутренними структурами планировщика, их использование должно быть заключено в захват/освобождение `sched_lock`. [[freebsd-proc]] ==== Структура proc Различные уровни эмуляции иногда требуют дополнительных данных для каждого процесса. Можно управлять отдельными структурами (списком, деревом и т.д.), содержащими эти данные для каждого процесса, но это может быть медленно и потреблять много памяти. Чтобы решить эту проблему, структура `proc` в FreeBSD содержит `p_emuldata` — указатель типа void на данные, специфичные для уровня эмуляции. Эта запись `proc` защищена мьютексом proc. Структура `proc` в FreeBSD содержит элемент `p_sysent`, который идентифицирует, под какой ABI работает данный процесс. Фактически, это указатель на упомянутый выше `sysentvec`. Таким образом, сравнивая этот указатель с адресом, по которому хранится структура `sysentvec` для данной ABI, мы можем эффективно определить, принадлежит ли процесс нашему эмуляционному слою. Код обычно выглядит следующим образом: [.programlisting] .... if (__predict_true(p->p_sysent != &elf_Linux(R)_sysvec)) return; .... Как видите, мы эффективно используем модификатор `__predict_true`, чтобы свести наиболее распространённый случай (процесс FreeBSD) к простой операции возврата, сохраняя высокую производительность. Этот код следует преобразовать в макрос, поскольку в настоящее время он не очень гибкий, например, мы не поддерживаем эмуляцию Linux(R)64, а также процессы Linux(R) в формате A.OUT на архитектуре i386. [[freebsd-vfs]] ==== VFS Подсистема VFS в FreeBSD очень сложна, но слой эмуляции Linux(R) использует лишь небольшую её часть через чётко определённый API. Она может работать как с vnode, так и с файловыми дескрипторами. Vnode представляет собой виртуальный vnode, то есть представление узла в VFS. Другое представление — это файловый дескриптор, который представляет открытый файл с точки зрения процесса. Файловый дескриптор может представлять сокет или обычный файл. Файловый дескриптор содержит указатель на свой vnode. Более одного файлового дескриптора могут указывать на один и тот же vnode. [[freebsd-namei]] ===== namei Функция man:namei[9] является центральной точкой входа для поиска и преобразования путей. Она проходит по пути шаг за шагом от начальной до конечной точки, используя функцию поиска, которая является внутренней для VFS. Системный вызов man:namei[9] может обрабатывать символьные ссылки, абсолютные и относительные пути. Когда путь ищется с помощью man:namei[9], он заносится в кэш имён. Это поведение можно отключить. Данная функция используется повсеместно в ядре, и её производительность крайне важна. [[freebsd-vn]] ===== vn_fullpath Функция man:vn_fullpath[9] предпринимает максимальные усилия для обхода кэша имён VFS и возвращает путь для заданного (заблокированного) vnode. Этот процесс ненадёжен, но в большинстве типичных случаев работает корректно. Ненадёжность обусловлена тем, что функция опирается на кэш VFS (она не обходит структуры на носителе), не работает с жёсткими ссылками и т.д. Данная процедура используется в нескольких местах Linuxulator. [[freebsd-vnode]] ===== Операции с vnode * `fgetvp` - по заданным потоку и номеру файлового дескриптора возвращает связанный vnode * man:vn_lock[9] - блокирует vnode * `vn_unlock` - разблокирует vnode * man:VOP_READDIR[9] - читает каталог, на который ссылается vnode * man:VOP_GETATTR[9] - получает атрибуты файла или каталога, на который ссылается vnode * man:VOP_LOOKUP[9] - выполняет поиск пути к заданному каталогу * man:VOP_OPEN[9] - открывает файл, на который ссылается vnode * man:VOP_CLOSE[9] - закрывает файл, на который ссылается vnode * man:vput[9] - уменьшает счетчик использования для vnode и разблокирует его * man:vrele[9] - уменьшает счетчик использования для vnode * man:vref[9] - увеличивает счетчик использования для vnode [[freebsd-file-handler]] ===== Операции обработчика файлов (handler) * `fget` - для заданного потока и номера файлового дескриптора возвращает связанный обработчик файла и делает на него ссылку * `fdrop` - освобождает ссылку на обработчик файлов * `fhold` - ссылается на обработчик файла [[md]] == Слой эмуляции Linux(R) - машинозависимая часть В этом разделе рассматривается реализация слоя эмуляции Linux(R) в операционной системе FreeBSD. Сначала описывается машинозависимая часть, рассказывающая о том, как и где реализовано взаимодействие между пользовательским пространством и ядром. Рассматриваются системные вызовы, сигналы, ptrace, ловушки и исправление стека. Эта часть посвящена архитектуре i386, но написана в общем виде, поэтому другие архитектуры не должны сильно отличаться. Следующая часть — машинонезависимая часть Linuxulator. Этот раздел охватывает только i386 и обработку ELF. A.OUT устарел и не поддерживается. [[syscall-handling]] === Обработка системных вызовов Обработка системных вызовов в основном реализована в файле [.filename]#linux_sysvec.c#, который покрывает большинство процедур, указанных в структуре `sysentvec`. Когда процесс Linux(R), выполняющийся на FreeBSD, делает системный вызов, общая процедура обработки системных вызовов вызывает linux prepsyscall для ABI Linux(R). [[linux-prepsyscall]] ==== Linux(R) prepsyscall Linux(R) передаёт аргументы системных вызовов через регистры (поэтому на i386 ограничено 6 параметрами), тогда как FreeBSD использует стек. Подпрограмма Linux(R) `prepsyscall` должна копировать параметры из регистров в стек. Порядок регистров следующий: `%ebx`, `%ecx`, `%edx`, `%esi`, `%edi`, `%ebp`. Однако это верно только для _большинства_ системных вызовов. Некоторые (особенно `clone`) используют другой порядок, но это, к счастью, легко исправить, добавив фиктивный параметр в прототип `linux_clone`. [[syscall-writing]] ==== Как писать системные вызовы Каждый системный вызов, реализованный в Linuxulator, должен иметь свой прототип с различными флагами в [.filename]#syscalls.master#. Формат файла следующий: [.programlisting] .... ... AUE_FORK STD { int linux_fork(void); } ... AUE_CLOSE NOPROTO { int close(int fd); } ... .... Первый столбец представляет номер системного вызова. Второй столбец предназначен для поддержки аудита. Третий столбец обозначает тип системного вызова. Он может быть `STD`, `OBSOL`, `NOPROTO` или `UNIMPL`. `STD` — это стандартный системный вызов с полным прототипом и реализацией. `OBSOL` означает устаревший вызов и определяет только прототип. `NOPROTO` означает, что системный вызов реализован в другом месте, поэтому не требует добавления префикса ABI и т.д. `UNIMPL` означает, что системный вызов будет заменён на `nosys` (системный вызов, который просто выводит сообщение о том, что вызов не реализован, и возвращает `ENOSYS`). Из файла [.filename]#syscalls.master# скрипт генерирует три файла: [.filename]#linux_syscall.h#, [.filename]#linux_proto.h# и [.filename]#linux_sysent.c#. Файл [.filename]#linux_syscall.h# содержит определения имён системных вызовов и их числовых значений, например: [.programlisting] .... ... #define LINUX_SYS_linux_fork 2 ... #define LINUX_SYS_close 6 ... .... [.filename]#linux_proto.h# содержит определения структур аргументов для каждого системного вызова, например: [.programlisting] .... struct linux_fork_args { register_t dummy; }; .... И, наконец, [.filename]#linux_sysent.c# содержит структуру, описывающую таблицу системных вызовов, используемую для фактической диспетчеризации системного вызова, например: [.programlisting] .... { 0, (sy_call_t *)linux_fork, AUE_FORK, NULL, 0, 0 }, /* 2 = linux_fork */ { AS(close_args), (sy_call_t *)close, AUE_CLOSE, NULL, 0, 0 }, /* 6 = close */ .... Как видно, `linux_fork` реализован в самом Linuxulator, поэтому определение имеет тип `STD` и не имеет аргументов, что демонстрируется структурой-заглушкой. С другой стороны, `close` — это просто псевдоним для настоящего FreeBSD man:close[2], поэтому у него нет связанной структуры аргументов Linux, и в системной таблице вызовов он не имеет префикса linux, так как вызывает настоящий man:close[2] в ядре. [[dummy-syscalls]] ==== Нереализованные системные вызовы Слой эмуляции Linux(R) не является полным, так как некоторые системные вызовы реализованы неправильно, а некоторые не реализованы вовсе. В слое эмуляции используется механизм для пометки нереализованных системных вызовов с помощью макроса `DUMMY`. Эти заглушки находятся в файле [.filename]#linux_dummy.c# в форме `DUMMY(syscall);`, которые затем преобразуются в различные вспомогательные файлы системных вызовов, а их реализация сводится к выводу сообщения о том, что данный системный вызов не реализован. Прототип `UNIMPL` не используется, потому что мы хотим иметь возможность идентифицировать имя вызванного системного вызова, чтобы понимать, какие системные вызовы более важны для реализации. [[signal-handling]] === Обработка сигналов Обработка сигналов обычно выполняется в ядре FreeBSD для всех вариантов бинарной совместимости с помощью вызова уровня, зависящего от совместимости. Слой совместимости Linux(R) определяет для этой цели процедуру `linux_sendsig`. [[linux-sendsig]] ==== Linux(R) sendsig Эта процедура сначала проверяет, установлен ли сигнал с флагом `SA_SIGINFO`, в таком случае она вызывает процедуру `linux_rt_sendsig` вместо текущей. Далее она выделяет (или повторно использует уже существующий) контекст обработчика сигнала, затем формирует список аргументов для обработчика сигнала. Она преобразует номер сигнала на основе таблицы преобразования сигналов, назначает обработчик, преобразует sigset. Затем она сохраняет контекст для процедуры `sigreturn` (различные регистры, преобразованный номер trap и маску сигналов). Наконец, она копирует контекст сигнала в пользовательское пространство и подготавливает контекст для фактического выполнения обработчика сигнала. [[linux-rt-sendsig]] ==== linux_rt_sendsig Эта процедура аналогична `linux_sendsig`, только подготовка контекста сигнала отличается. Она добавляет `siginfo`, `ucontext` и некоторые части POSIX(R). Стоит рассмотреть возможность объединения этих двух функций с выгодой в виде меньшего дублирования кода и, возможно, даже более быстрого выполнения. [[linux-sigreturn]] ==== linux_sigreturn Этот системный вызов используется для возврата из обработчика сигнала. Он выполняет некоторые проверки безопасности и восстанавливает исходный контекст процесса. Также он разблокирует сигнал в маске сигналов процесса. [[ptrace]] === Ptrace Многие производные UNIX(R) реализуют системный вызов man:ptrace[2] для обеспечения различных функций отслеживания и отладки. Этот механизм позволяет трассирующему процессу получать различную информацию о трассируемом процессе, такую как дампы регистров, любую память из адресного пространства процесса и т.д., а также трассировать процесс, например, пошагово выполнять инструкции или между системными вызовами (сисколлами и ловушками). man:ptrace[2] также позволяет устанавливать различную информацию в трассируемом процессе (регистры и т.д.). man:ptrace[2] является стандартом для UNIX(R), реализованным в большинстве UNIX(R)-систем по всему миру. Эмуляция Linux(R) в FreeBSD реализует механизм man:ptrace[2] в файле [.filename]#linux_ptrace.c#. Функции для преобразования регистров между Linux(R) и FreeBSD и фактический системный вызов эмуляции man:ptrace[2]. Системный вызов представляет собой длинный блок switch, который реализует свой аналог в FreeBSD для каждой команды man:ptrace[2]. Команды man:ptrace[2] в основном одинаковы между Linux(R) и FreeBSD, поэтому обычно требуется лишь небольшая модификация. Например, `PT_GETREGS` в Linux(R) работает с непосредственными данными, в то время как FreeBSD использует указатель на данные, поэтому после выполнения (нативного) системного вызова man:ptrace[2] необходимо выполнить copyout для сохранения семантики Linux(R). Реализация man:ptrace[2] в Linuxulator имеет известные недостатки. Наблюдались паники при использовании `strace` (который является потребителем man:ptrace[2]) в среде Linuxulator. Также `PT_SYSCALL` не реализован. [[traps]] === Ловушки (trap) Всякий раз, когда процесс Linux(R), выполняющийся в слое эмуляции, вызывает прерывание (trap), само прерывание обрабатывается прозрачно, за исключением преобразования прерывания. Linux(R) и FreeBSD расходятся во мнениях относительно того, что является прерыванием, поэтому этот вопрос решается здесь. Код на самом деле очень короткий: [.programlisting] .... static int translate_traps(int signal, int trap_code) { if (signal != SIGBUS) return signal; switch (trap_code) { case T_PROTFLT: case T_TSSFLT: case T_DOUBLEFLT: case T_PAGEFLT: return SIGSEGV; default: return signal; } } .... [[stack-fixup]] === Исправление стека Динамический редактор связей RTLD ожидает так называемые AUX-теги на стеке во время выполнения `execve`, поэтому необходимо выполнить исправление, чтобы это обеспечить. Конечно, каждая система RTLD отличается, поэтому уровень эмуляции должен предоставлять собственную процедуру исправления стека. Linuxulator делает именно это. Функция `elf_linux_fixup` просто копирует AUX-теги на стек и корректирует стек пользовательского процесса, чтобы он указывал сразу после этих тегов. Таким образом, RTLD работает умным способом. [[aout-support]] === Поддержка A.OUT Эмуляционный слой Linux(R) на i386 также поддерживает бинарные файлы Linux(R) в формате A.OUT. Почти всё, что описано в предыдущих разделах, должно быть реализовано для поддержки A.OUT (кроме перевода ловушек и отправки сигналов). Поддержка бинарных файлов A.OUT больше не поддерживается, в частности, эмуляция 2.6 с ними не работает, но это не вызывает никаких проблем, так как linux-base в портах, вероятно, вообще не поддерживает бинарные файлы A.OUT. Эта поддержка, скорее всего, будет удалена в будущем. Большая часть кода, необходимого для загрузки бинарных файлов Linux(R) A.OUT, находится в файле [.filename]#imgact_linux.c#. [[mi]] == Слой эмуляции Linux(R) - машинонезависимая часть В этом разделе рассматривается машинонезависимая часть Linuxulator. Он охватывает инфраструктуру эмуляции, необходимую для эмуляции Linux(R) 2.6, реализацию thread local storage (TLS) (на i386) и фьютексы. Затем мы кратко обсуждаем некоторые системные вызовы. [[nptl-desc]] === Описание NPTL Одним из основных направлений прогресса в разработке Linux(R) 2.6 стала поддержка потоков. До версии 2.6 поддержка потоков в Linux(R) реализовывалась в библиотеке linuxthreads. Эта библиотека представляла собой частичную реализацию потоков POSIX(R). Потоки создавались как отдельные процессы с использованием системного вызова `clone`, что позволяло им разделять адресное пространство (и другие ресурсы). Основными недостатками такого подхода были разные PID для каждого потока, некорректная обработка сигналов (с точки зрения pthreads) и т.д. Кроме того, производительность оставляла желать лучшего (использование сигналов `SIGUSR` для синхронизации потоков, потребление ресурсов ядра и т.п.), поэтому для решения этих проблем была разработана новая система потоков под названием NPTL. Библиотека NPTL была сосредоточена на двух вещах, но появилась третья, поэтому её обычно считают частью NPTL. Этими двумя вещами были встраивание потоков в структуру процесса и фьютекс. Дополнительной третьей вещью стал TLS, который не требуется напрямую NPTL, но вся пользовательская библиотека NPTL зависит от него. Эти улучшения привели к значительному росту производительности и соответствию стандартам. В настоящее время NPTL является стандартной библиотекой потоков в системах Linux(R). Реализация Linuxulator в FreeBSD подходит к NPTL в трёх основных направлениях: TLS, фьютекс и изменение PID, что предназначено для эмуляции потоков Linux(R). В следующих разделах описывается каждое из этих направлений. [[linux26-emu]] === Инфраструктура эмуляции Linux(R) 2.6 Эти разделы посвящены тому, как управляются потоки Linux(R) и как мы моделируем это в FreeBSD. [[linux26-runtime]] ==== Определение эмуляции 2.6 во время выполнения Слой эмуляции Linux(R) в FreeBSD поддерживает динамическую настройку эмулируемой версии. Это выполняется с помощью man:sysctl[8], а именно `compat.linux.osrelease`. Установка этого man:sysctl[8] влияет на поведение слоя эмуляции во время выполнения. При установке значения 2.6.x устанавливается переменная `linux_use_linux26`, а при установке другого значения она остаётся сброшенной. Эта переменная (а также аналогичные переменные для каждой клетки) определяет, используется ли в коде инфраструктура 2.6 (в основном, преобразование PID). Настройка версии применяется глобально для всей системы и влияет на все процессы Linux(R). Не следует изменять man:sysctl[8] во время выполнения любого бинарного файла Linux(R), так как это может привести к проблемам. [[linux-proc-thread]] ==== Идентификаторы процессов и потоков Linux(R) Семантика потоков в Linux(R) немного запутанная и использует совершенно другую терминологию по сравнению с FreeBSD. Процесс в Linux(R) состоит из `struct task`, включающей два поля идентификаторов — PID и TGID. PID — это _не_ идентификатор процесса, а идентификатор потока. TGID идентифицирует группу потоков, другими словами, процесс. Для однопоточного процесса PID равен TGID. -Поток в NPTL — это обычный процесс, у которого TGID не равен PID и есть групповой лидер, отличный от него самого (и, конечно, общая виртуальная память и т.д.). Все остальное происходит так же, как и с обычным процессом. Нет разделения общего состояния на внешнюю структуру, как в FreeBSD. Это создает некоторое дублирование информации и возможную несогласованность данных. Ядро Linux(R), похоже, использует информацию о задаче -> группе в одних местах и информацию о задаче в других, что не очень последовательно и выглядит небезопасно с точки зрения возможных ошибок. +Поток в NPTL — это обычный процесс, у которого TGID не равен PID и есть групповой лидер, отличный от него самого (и, конечно, общая виртуальная память и т.д.). Все остальное происходит так же, как и с обычным процессом. Нет разделения общего состояния на внешнюю структуру, как в FreeBSD. Это создаёт некоторое дублирование информации и возможную несогласованность данных. Ядро Linux(R), похоже, использует информацию о задаче -> группе в одних местах и информацию о задаче в других, что не очень последовательно и выглядит небезопасно с точки зрения возможных ошибок. -Каждый поток NPTL создается вызовом системного вызова `clone` с определённым набором флагов (подробнее в следующем подразделе). NPTL реализует строгую модель потоков 1:1. +Каждый поток NPTL создаётся вызовом системного вызова `clone` с определённым набором флагов (подробнее в следующем подразделе). NPTL реализует строгую модель потоков 1:1. В FreeBSD мы эмулируем потоки NPTL с помощью обычных процессов FreeBSD, которые разделяют виртуальную память и т.д., а гимнастика с PID просто имитируется в специфической для эмуляции структуре, прикреплённой к процессу. Структура, прикреплённая к процессу, выглядит следующим образом: [.programlisting] .... struct linux_emuldata { pid_t pid; int *child_set_tid; /* in clone(): Child.s TID to set on clone */ int *child_clear_tid;/* in clone(): Child.s TID to clear on exit */ struct linux_emuldata_shared *shared; int pdeath_signal; /* parent death signal */ LIST_ENTRY(linux_emuldata) threads; /* list of linux threads */ }; .... PID используется для идентификации процесса FreeBSD, к которому присоединена эта структура. `child_se_tid` и `child_clear_tid` используются для копирования адреса TID при завершении и создании процесса. Указатель `shared` указывает на структуру, разделяемую между потоками. Переменная `pdeath_signal` определяет сигнал завершения родительского процесса, а указатель `threads` используется для связывания этой структуры со списком потоков. Структура `linux_emuldata_shared` выглядит следующим образом: [.programlisting] .... struct linux_emuldata_shared { int refs; pid_t group_pid; LIST_HEAD(, linux_emuldata) threads; /* head of list of linux threads */ }; .... `refs` — это счётчик ссылок, используемый для определения момента, когда можно освободить структуру, чтобы избежать утечек памяти. `group_pid` служит для идентификации PID (= TGID) всего процесса (= группы потоков). Указатель `threads` является головой списка потоков в процессе. Структуру `linux_emuldata` можно получить из процесса с помощью `em_find`. Прототип функции выглядит следующим образом: [.programlisting] .... struct linux_emuldata *em_find(struct proc *, int locked); .... Здесь `proc` — это процесс, из которого мы хотим получить структуру `emuldata`, а параметр `locked` определяет, нужно ли блокировать. Допустимые значения — `EMUL_DOLOCK` и `EMUL_DOUNLOCK`. Подробнее о блокировке позже. [[pid-mangling]] ==== Преобразование PID Поскольку между FreeBSD и Linux(R) существуют различия в представлении идентификатора процесса (PID) и идентификатора потока (TID), нам необходимо преобразовывать эти понятия. Это достигается за счёт модификации PID. Это означает, что мы изменяем представление о PID (=TGID) и TID (=PID) между ядром и пользовательским пространством. Основное правило заключается в следующем: в ядре (в Linuxulator) `PID = PID`, а `TGID = shared -> group_pid`; для пользовательского пространства мы представляем `PID = shared -> group_pid` и `TID = proc -> p_pid`. Член `PID` в структуре `linux_emuldata` является FreeBSD PID. Вышесказанное в основном влияет на системные вызовы getpid, getppid, gettid. В случаях, где мы используем PID/TGID соответственно. При копировании TID в `child_clear_tid` и `child_set_tid` мы копируем FreeBSD PID. [[clone-syscall]] ==== Системный вызов clone `clone` — это системный вызов, с помощью которого создаются потоки в Linux(R). Прототип системного вызова выглядит следующим образом: [.programlisting] .... int linux_clone(l_int flags, void *stack, void *parent_tidptr, int dummy, void * child_tidptr); .... Параметр `flags` указывает системному вызову, как именно процессы должны быть клонированы. Как описано выше, Linux(R) может создавать процессы, разделяющие различные ресурсы независимо, например, два процесса могут разделять файловые дескрипторы, но не виртуальную память и т.д. Последний байт параметра `flags` является сигналом завершения для вновь созданного процесса. Параметр `stack`, если он не `NULL`, указывает, где находится стек потока, а если он `NULL`, предполагается копирование при записи стека вызывающего процесса (т.е. делать то же, что делает обычная функция man:fork[2]). Параметр `parent_tidptr` используется как адрес для копирования PID процесса (т.е. идентификатора потока) после того, как процесс достаточно инициализирован, но ещё не готов к выполнению. Параметр `dummy` присутствует из-за очень странного соглашения о вызовах этого системного вызова на i386. Он использует регистры напрямую и не позволяет компилятору делать это, что приводит к необходимости использования фиктивного системного вызова. Параметр `child_tidptr` используется как адрес для копирования PID после завершения ветвления процесса и при его завершении. Системный вызов продолжает выполнение, устанавливая соответствующие флаги в зависимости от переданных аргументов. Например, `CLONE_VM` преобразуется в RFMEM (общее адресное пространство) и т.д. Единственная тонкость здесь — это `CLONE_FS` и `CLONE_FILES`, поскольку FreeBSD не позволяет устанавливать их отдельно, поэтому мы эмулируем это, не устанавливая RFFDG (копирование таблицы файловых дескрипторов и другой информации о файловой системе), если задан любой из этих флагов. Это не вызывает проблем, так как эти флаги всегда устанавливаются вместе. После установки флагов процесс создаётся с помощью внутренней процедуры `fork1`, при этом процесс настраивается так, чтобы не помещаться в очередь выполнения (т.е. не становиться исполняемым). После завершения ветвления мы, при необходимости, изменяем родителя для нового процесса, чтобы эмулировать семантику `CLONE_PARENT`. Следующий шаг — создание данных эмуляции. Потоки в Linux(R) не отправляют сигналы своим родителям, поэтому мы устанавливаем сигнал завершения в 0, чтобы отключить эту возможность. Затем выполняется настройка `child_set_tid` и `child_clear_tid`, что активирует соответствующую функциональность далее в коде. На этом этапе мы копируем PID по адресу, указанному в `parent_tidptr`. Установка стека процесса выполняется простой перезаписью регистра `%esp` (`%rsp` на amd64) в кадре потока. Далее настраивается TLS для нового процесса. После этого может быть эмулирована семантика man:vfork[2], и, наконец, новый процесс помещается в очередь выполнения, а его PID возвращается родительскому процессу через возвращаемое значение `clone`. Системный вызов `clone` способен и фактически используется для эмуляции классических системных вызовов man:fork[2] и man:vfork[2]. Более новые версии glibc в случае ядра 2.6 используют `clone` для реализации системных вызовов man:fork[2] и man:vfork[2]. [[locking]] ==== Блокировка Блокировка реализована на уровне подсистем, поскольку не ожидается высокой конкуренции за эти ресурсы. Существует две блокировки: `emul_lock`, используемая для защиты манипуляций с `linux_emuldata`, и `emul_shared_lock`, используемая для манипуляций с `linux_emuldata_shared`. `emul_lock` представляет собой неспящий блокирующий мьютекс, в то время как `emul_shared_lock` — это спящий блокирующий `sx_lock`. Благодаря блокировке на уровне подсистем мы можем объединять некоторые блокировки, поэтому em_find предлагает доступ без блокировки. [[tls]] === TLS Этот раздел посвящён TLS, также известному как локальное хранилище потока. [[trheading-intro]] ==== Введение в многопоточность В компьютерных науках потоки (threads) — это сущности внутри процесса, которые могут планироваться независимо друг от друга. Потоки в процессе разделяют общие данные процесса (например, файловые дескрипторы), но также имеют свой собственный стек для своих данных. Иногда возникает необходимость в данных, специфичных для конкретного потока, но доступных на уровне процесса. Например, имя выполняемого потока или что-то подобное. Традиционный API для работы с потоками в UNIX® — pthreads — предоставляет способ сделать это через функции `man:pthread_key_create[3]`, `man:pthread_setspecific[3]` и `man:pthread_getspecific[3]`, где поток может создать ключ к локальным данным потока и использовать `man:pthread_getspecific[3]` или `man:pthread_getspecific[3]` для управления этими данными. Легко заметить, что это не самый удобный способ. Поэтому различные разработчики компиляторов C/C++ предложили более удобный метод. Они ввели новое ключевое слово `thread`, которое указывает, что переменная является специфичной для потока. Также был разработан новый метод доступа к таким переменным (по крайней мере, на архитектуре i386). Метод pthreads обычно реализуется в пользовательском пространстве в виде простой таблицы поиска. Производительность такого решения не очень высока. Новый метод использует (на i386) сегментные регистры для адресации области, где хранится TLS (Thread-Local Storage), так что фактический доступ к переменной потока сводится к добавлению сегментного регистра к адресу, таким образом обращаясь через него. Сегментные регистры, обычно `%gs` и `%fs`, действуют как селекторы сегментов. Каждый поток имеет свою собственную область, где хранятся локальные данные потока, и сегмент должен загружаться при каждом переключении контекста. Этот метод очень быстрый и используется практически повсеместно в мире UNIX® на архитектуре i386. И FreeBSD, и Linux® реализуют этот подход, и он даёт очень хорошие результаты. Единственный недостаток — необходимость перезагружать сегмент при каждом переключении контекста, что может замедлять переключения. FreeBSD пытается минимизировать эти накладные расходы, используя только 1 дескриптор сегмента, в то время как Linux® использует 3. Интересно, что почти ничто не использует больше 1 дескриптора (только Wine, кажется, использует 2), поэтому Linux® платит эту необязательную цену при переключении контекстов. [[i386-segs]] ==== Сегменты на i386 Архитектура i386 реализует так называемые сегменты. Сегмент — это описание области памяти. Он включает базовый адрес (начало) области памяти, её конец (границу), тип, защиту и т.д. Доступ к памяти, описываемой сегментом, может осуществляться с использованием регистров селекторов сегментов (`%cs`, `%ds`, `%ss`, `%es`, `%fs`, `%gs`). Например, предположим, что у нас есть сегмент с базовым адресом 0x1234 и длиной, а также следующий код: [.programlisting] .... mov %edx,%gs:0x10 .... Это загрузит содержимое регистра `%edx` в ячейку памяти по адресу 0x1244. Некоторые сегментные регистры имеют специальное назначение, например, `%cs` используется для сегмента кода, а `%ss` — для сегмента стека, но `%fs` и `%gs` обычно не используются. Сегменты хранятся либо в глобальной таблице GDT, либо в локальной таблице LDT. Доступ к LDT осуществляется через запись в GDT. LDT может хранить больше типов сегментов. LDT может быть отдельной для каждого процесса. Обе таблицы определяют до 8191 записей. [[linux-i386]] ==== Реализация на Linux(R) i386 Существует два основных способа настройки TLS в Linux(R). Он может быть настроен при клонировании процесса с использованием системного вызова `clone` или с помощью вызова `set_thread_area`. Когда процесс передаёт флаг `CLONE_SETTLS` в `clone`, ядро ожидает, что память, на которую указывает регистр `%esi`, будет содержать пользовательское представление сегмента в Linux(R), которое преобразуется в машинное представление сегмента и загружается в слот GDT. Слот GDT может быть указан номером или можно использовать -1, что означает, что система сама должна выбрать первый свободный слот. На практике подавляющее большинство программ используют только одну запись TLS и не заботятся о номере записи. Мы используем это в эмуляции и фактически зависим от этого. [[tls-emu]] ==== Эмуляция Linux(R) TLS [[tls-i386]] ===== i386 Загрузка TLS для текущего потока происходит путем вызова `set_thread_area`, тогда как загрузка TLS для второго процесса в `clone` выполняется в отдельном блоке в `clone`. Эти две функции очень похожи. Единственное различие заключается в фактической загрузке сегмента GDT, которая происходит при следующем переключении контекста для вновь созданного процесса, в то время как `set_thread_area` должен загрузить его напрямую. Код в основном делает следующее. Он копирует дескриптор сегмента в формате Linux(R) из пользовательского пространства. Код проверяет номер дескриптора, но поскольку он различается между FreeBSD и Linux(R), мы немного имитируем его. Мы поддерживаем только индексы 6, 3 и -1. Число 6 — это оригинальный номер Linux(R), 3 — оригинальный номер FreeBSD, а -1 означает авто-выбор. Затем мы устанавливаем номер дескриптора на константу 3 и копируем его обратно в пользовательское пространство. Мы полагаемся на то, что процесс в пользовательском пространстве использует номер из дескриптора, но это работает в большинстве случаев (никогда не встречалось ситуации, когда это не срабатывало), так как процесс в пользовательском пространстве обычно передаёт 1. Затем мы преобразуем дескриптор из формата Linux(R) в машинозависимую форму (т.е. независимую от операционной системы) и копируем его в дескриптор сегмента, определённый FreeBSD. Наконец, мы можем загрузить его. Мы назначаем дескриптор PCB потока (блок управления процессом) и загружаем сегмент `%gs` с помощью `load_gs`. Эта загрузка должна выполняться в критической секции, чтобы ничто не могло нас прервать. Случай `CLONE_SETTLS` работает точно так же, только загрузка с помощью `load_gs` не выполняется. Сегмент, используемый для этого (сегмент номер 3), разделяется между процессами FreeBSD и Linux(R), поэтому слой эмуляции Linux(R) не добавляет накладных расходов по сравнению с обычным FreeBSD. [[tls-amd64]] ===== amd64 Реализация amd64 аналогична реализации i386, но изначально не использовался 32-битный дескриптор сегмента для этой цели (поэтому даже нативные пользователи 32-битного TLS не работали), поэтому нам пришлось добавить такой сегмент и реализовать его загрузку при каждом переключении контекста (когда установлен флаг, сигнализирующий о использовании 32-битного режима). Кроме этого, загрузка TLS точно такая же, только номера сегментов отличаются, а формат дескриптора и загрузка немного различаются. [[futexes]] === Фьютексы [[sync-intro]] ==== Введение в синхронизацию Потокам требуется некоторая синхронизация, и POSIX(R) предоставляет несколько её видов: мьютексы для взаимного исключения, блокировки чтения-записи для взаимного исключения с преобладанием операций чтения над записями и условные переменные для сигнализации об изменении состояния. Интересно отметить, что в API потоков POSIX(R) отсутствует поддержка семафоров. Реализации этих механизмов синхронизации сильно зависят от типа поддержки потоков, которая у нас есть. В чистой модели 1:M (пользовательское пространство) реализация может быть выполнена исключительно в пользовательском пространстве и, следовательно, быть очень быстрой (условные переменные, вероятно, будут реализованы с использованием сигналов, т.е. не быстро) и простой. В модели 1:1 ситуация также довольно ясна — потоки должны синхронизироваться с использованием средств ядра (что очень медленно, поскольку требуется выполнение системного вызова). Смешанный сценарий M:N просто комбинирует первый и второй подходы или полагается исключительно на ядро. Синхронизация потоков является важной частью программирования с использованием потоков, и её производительность может значительно влиять на итоговую программу. Недавние тесты в операционной системе FreeBSD показали, что улучшенная реализация `sx_lock` дала 40% прироста скорости в _ZFS_ (где активно используются блокировки sx), это внутренние механизмы ядра, но это наглядно демонстрирует, насколько важна производительность примитивов синхронизации. Многопоточные программы должны быть написаны с минимальной конкуренцией за блокировки. В противном случае, вместо выполнения полезной работы поток просто ожидает блокировку. В результате, наиболее хорошо написанные многопоточные программы демонстрируют низкую конкуренцию за блокировки. [[futex-intro]] ==== Введение в фьютексы Linux(R) реализует 1:1 потоковую модель, то есть использует примитивы синхронизации в ядре. Как упоминалось ранее, хорошо написанные многопоточные программы имеют низкую конкуренцию за блокировки. Таким образом, типичная последовательность может выполняться как два атомарных увеличения/уменьшения счётчика ссылок мьютекса, что очень быстро, как показано в следующем примере: [.programlisting] .... pthread_mutex_lock(&mutex); ... pthread_mutex_unlock(&mutex); .... 1:1 threading вынуждает нас выполнять два системных вызова для этих вызовов мьютекса, что очень медленно. Решение, реализованное в Linux(R) 2.6, называется фьютексы. Фьютексы выполняют проверку на конкуренцию в пользовательском пространстве и вызывают примитивы ядра только в случае конкуренции. Таким образом, типичный случай обходится без вмешательства ядра. Это обеспечивает достаточно быструю и гибкую реализацию примитивов синхронизации. [[futex-api]] ==== API фьютексов Системный вызов futex выглядит следующим образом: [.programlisting] .... int futex(void *uaddr, int op, int val, struct timespec *timeout, void *uaddr2, int val3); .... В этом примере `uaddr` — это адрес мьютекса в пользовательском пространстве, `op` — операция, которую мы собираемся выполнить, а остальные параметры имеют значение, зависящее от конкретной операции. Фьютексы реализуют следующие операции: * `FUTEX_WAIT` * `FUTEX_WAKE` * `FUTEX_FD` * `FUTEX_REQUEUE` * `FUTEX_CMP_REQUEUE` * `FUTEX_WAKE_OP` [[futex-wait]] ===== FUTEX_WAIT Эта операция проверяет, что по адресу `uaddr` записано значение `val`. Если нет, возвращается `EWOULDBLOCK`, в противном случае поток ставится в очередь на фьютекс и приостанавливается. Если аргумент `timeout` не равен нулю, он задает максимальное время ожидания, в противном случае ожидание бесконечно. [[futex-wake]] ===== FUTEX_WAKE Эта операция захватывает фьютекс по адресу `uaddr` и пробуждает первые `val` фьютексов, ожидающих в очереди на этом фьютексе. [[futex-fd]] ===== FUTEX_FD Эта операция связывает файловый дескриптор с заданным фьютексом. [[futex-requeue]] ===== FUTEX_REQUEUE Эта операция берет `val` потоков, ожидающих на фьютексе по адресу `uaddr`, пробуждает их и берет следующие `val2` потоков, перемещая их в очередь фьютекса по адресу `uaddr2`. [[futex-cmp-requeue]] ===== FUTEX_CMP_REQUEUE Эта операция делает то же самое, что и `FUTEX_REQUEUE`, но сначала проверяет, что `val3` равно `val`. [[futex-wake-op]] ===== FUTEX_WAKE_OP Эта операция выполняет атомарную операцию над `val3` (которая содержит закодированное другое значение) и `uaddr`. Затем она пробуждает `val` потоков на фьютексе по адресу `uaddr`, и если атомарная операция вернула положительное число, пробуждает `val2` потоков на фьютексе по адресу `uaddr2`. Операции, реализованные в `FUTEX_WAKE_OP`: * `FUTEX_OP_SET` * `FUTEX_OP_ADD` * `FUTEX_OP_OR` * `FUTEX_OP_AND` * `FUTEX_OP_XOR` [NOTE] ==== В прототипе системного вызова futex отсутствует параметр `val2`. Значение `val2` берётся из параметра `struct timespec *timeout` для операций `FUTEX_REQUEUE`, `FUTEX_CMP_REQUEUE` и `FUTEX_WAKE_OP`. ==== [[futex-emu]] ==== Эмуляция фьютексов в FreeBSD Эмуляция futex в FreeBSD взята из NetBSD и дополнительно расширена нами. Она размещена в файлах `linux_futex.c` и [.filename]#linux_futex.h#. Структура `futex` выглядит следующим образом: [.programlisting] .... struct futex { void *f_uaddr; int f_refcount; LIST_ENTRY(futex) f_list; TAILQ_HEAD(lf_waiting_paroc, waiting_proc) f_waiting_proc; }; .... И структура `waiting_proc` выглядит следующим образом: [.programlisting] .... struct waiting_proc { struct thread *wp_t; struct futex *wp_new_futex; TAILQ_ENTRY(waiting_proc) wp_list; }; .... [[futex-get]] ===== futex_get / futex_put -Фьютекс получается с помощью функции `futex_get`, которая выполняет поиск в линейном списке фьютексов и возвращает найденный или создает новый. При освобождении фьютекса после использования вызывается функция `futex_put`, которая уменьшает счетчик ссылок фьютекса, и если счетчик достигает нуля, фьютекс освобождается. +Фьютекс получается с помощью функции `futex_get`, которая выполняет поиск в линейном списке фьютексов и возвращает найденный или создаёт новый. При освобождении фьютекса после использования вызывается функция `futex_put`, которая уменьшает счетчик ссылок фьютекса, и если счетчик достигает нуля, фьютекс освобождается. [[futex-sleep]] ===== futex_sleep -Когда фьютекс ставит поток в очередь на ожидание, он создает структуру `working_proc` и помещает эту структуру в список внутри структуры futex, после чего просто выполняет man:tsleep[9] для приостановки потока. Ожидание может быть ограничено по времени. После возврата из man:tsleep[9] (поток был разбужен или истекло время ожидания) структура `working_proc` удаляется из списка и уничтожается. Все это выполняется в функции `futex_sleep`. Если мы были разбужены с помощью `futex_wake`, у нас установлен `wp_new_futex`, поэтому мы ожидаем на нём. Таким образом, фактическое перемещение выполняется в этой функции. +Когда фьютекс ставит поток в очередь на ожидание, он создаёт структуру `working_proc` и помещает эту структуру в список внутри структуры futex, после чего просто выполняет man:tsleep[9] для приостановки потока. Ожидание может быть ограничено по времени. После возврата из man:tsleep[9] (поток был разбужен или истекло время ожидания) структура `working_proc` удаляется из списка и уничтожается. Все это выполняется в функции `futex_sleep`. Если мы были разбужены с помощью `futex_wake`, у нас установлен `wp_new_futex`, поэтому мы ожидаем на нём. Таким образом, фактическое перемещение выполняется в этой функции. [[futex-wake-2]] ===== futex_wake Пробуждение потока, ожидающего на фьютексе, выполняется в функции `futex_wake`. Сначала в этой функции мы имитируем странное поведение Linux(R), где пробуждаются N потоков для всех операций, за исключением того, что операции REQUEUE выполняются на N+1 потоках. Однако обычно это не имеет значения, так как мы пробуждаем все потоки. Далее в функции в цикле мы пробуждаем n потоков, после чего проверяем, есть ли новый фьютекс для перестановки. Если есть, мы переставляем до n2 потоков на новый futex. Это взаимодействует с `futex_sleep`. [[futex-wake-op-2]] ===== futex_wake_op Операция `FUTEX_WAKE_OP` довольно сложна. Сначала мы получаем два фьютекса по адресам `uaddr` и `uaddr2`, затем выполняем атомарную операцию с использованием `val3` и `uaddr2`. После этого пробуждаются `val` ожидающих на первом фьютексе, и если условие атомарной операции выполняется, мы пробуждаем `val2` (т.е. `timeout`) ожидающих на втором фьютексе. [[futex-atomic-op]] ===== Атомарная операция на фьютексе Атомарная операция принимает два параметра `encoded_op` и `uaddr`. Закодированная операция включает саму операцию, сравниваемое значение, аргумент операции и аргумент сравнения. Псевдокод операции выглядит следующим образом: [.programlisting] .... oldval = *uaddr2 *uaddr2 = oldval OP oparg .... И это выполняется атомарно. Сначала происходит копирование числа по адресу `uaddr`, а затем выполняется операция. Код обрабатывает ошибки страниц, и если ошибки не происходит, `oldval` сравнивается с аргументом `cmparg` с помощью компаратора cmp. [[futex-locking]] ===== Блокировка фьютекса Реализация фьютексов использует два списка блокировок для защиты `sx_lock` и глобальных блокировок (либо Giant, либо другой `sx_lock`). Каждая операция выполняется заблокированной от начала до самого конца. [[syscall-impl]] === Реализация различных системных вызовов В этом разделе я опишу несколько менее значимых системных вызовов, которые стоит упомянуть, потому что их реализация неочевидна или эти вызовы представляют интерес с другой точки зрения. [[syscall-at]] ==== *семейство системных вызовов at Во время разработки ядра Linux(R) 2.6.16 были добавлены *at-системные вызовы. Эти системные вызовы (например, `openat`) работают точно так же, как их аналоги без at, за исключением параметра `dirfd`. Этот параметр определяет местоположение файла, над которым выполняется системный вызов. Если параметр `filename` является абсолютным, `dirfd` игнорируется, но если путь к файлу относительный, `dirfd` вступает в игру. Параметр `dirfd` представляет собой каталог, относительно которого проверяется относительный путь. Параметр `dirfd` является файловым дескриптором некоторого каталога или `AT_FDCWD`. Например, системный вызов `openat` может выглядеть следующим образом: [.programlisting] .... file descriptor 123 = /tmp/foo/, current working directory = /tmp/ openat(123, /tmp/bah\, flags, mode) /* opens /tmp/bah */ openat(123, bah\, flags, mode) /* opens /tmp/foo/bah */ openat(AT_FDWCWD, bah\, flags, mode) /* opens /tmp/bah */ openat(stdio, bah\, flags, mode) /* returns error because stdio is not a directory */ .... Эта инфраструктура необходима для избежания состояний гонки при открытии файлов вне рабочего каталога. Представьте, что процесс состоит из двух потоков, потока A и потока B. Поток A выполняет `open(./tmp/foo/bah., flags, mode)`, и перед возвратом управления он вытесняется, и начинает выполняться поток B. Поток B не учитывает потребности потока A и переименовывает или удаляет [.filename]#/tmp/foo/#. Возникает состояние гонки. Чтобы избежать этого, мы можем открыть [.filename]#/tmp/foo# и использовать его как `dirfd` для системного вызова `openat`. Это также позволяет пользователю реализовать рабочие каталоги для каждого потока. Семейство *at системных вызовов Linux(R) включает: `linux_openat`, `linux_mkdirat`, `linux_mknodat`, `linux_fchownat`, `linux_futimesat`, `linux_fstatat64`, `linux_unlinkat`, `linux_renameat`, `linux_linkat`, `linux_symlinkat`, `linux_readlinkat`, `linux_fchmodat` и `linux_faccessat`. Все они реализованы с использованием модифицированной функции man:namei[9] и простого слоя обёртки. [[implementation]] ===== Реализация Реализация выполнена путем изменения функции man:namei[9] (описанной выше) для приема дополнительного параметра `dirfd` в структуре `nameidata`, который указывает начальную точку для поиска пути вместо использования текущего рабочего каталога каждый раз. Преобразование `dirfd` из номера файлового дескриптора в vnode выполняется в нативных *at-системных вызовах. Когда `dirfd` равен `AT_FDCWD`, запись `dvp` в структуре `nameidata` имеет значение `NULL`, но если `dirfd` представляет другой номер, мы получаем файл по этому дескриптору, проверяем его валидность и, если к нему прикреплен vnode, получаем этот vnode. Затем проверяем, является ли этот vnode каталогом. В самой функции man:namei[9] мы просто заменяем vnode `dvp` на переменную `dp` в функции man:namei[9], которая определяет начальную точку. Функция man:namei[9] используется не напрямую, а через цепочку различных функций на разных уровнях. Например, `openat` работает следующим образом: [.programlisting] .... openat() --> kern_openat() --> vn_open() -> namei() .... По этой причине `kern_open` и `vn_open` должны быть изменены для включения дополнительного параметра `dirfd`. Слой совместимости для них не создаётся, так как пользователей этих функций немного и их можно легко адаптировать. Данная общая реализация позволяет FreeBSD реализовать свои собственные *at-системные вызовы. Это обсуждается в настоящее время. [[ioctl]] ==== Ioctl Интерфейс ioctl довольно хрупок из-за своей обобщённости. Необходимо учитывать, что устройства в Linux(R) и FreeBSD различаются, поэтому требуется особая осторожность для корректной работы эмуляции ioctl. Обработка ioctl реализована в файле [.filename]#linux_ioctl.c#, где определена функция `linux_ioctl`. Эта функция просто перебирает наборы обработчиков ioctl, чтобы найти обработчик, реализующий данную команду. Системный вызов ioctl имеет три параметра: файловый дескриптор, команду и аргумент. Команда представляет собой 16-битное число, которое теоретически делится на старшие 8 бит, определяющие класс команды ioctl, и младшие 8 бит, которые являются конкретной командой в данном наборе. Эмуляция использует это разделение. Реализованы обработчики для каждого набора, такие как `sound_handler` или `disk_handler`. Каждый обработчик имеет определённые максимальную и минимальную команды, которые используются для выбора нужного обработчика. Существуют небольшие проблемы с этим подходом, поскольку Linux(R) не всегда последовательно использует разделение на наборы, поэтому иногда ioctls для другого набора оказываются внутри набора, к которому они не должны принадлежать (например, SCSI generic ioctls внутри набора cdrom и т.д.). В настоящее время FreeBSD реализует не так много ioctls Linux(R) (по сравнению с NetBSD, например), но планируется перенести их из NetBSD. Тенденция такова, что ioctls Linux(R) используются даже в родных драйверах FreeBSD для упрощения портирования приложений. [[debugging]] ==== Отладка Каждый системный вызов должен поддерживать отладку. Для этой цели мы вводим небольшую инфраструктуру. У нас есть механизм `ldebug`, который определяет, нужно ли отлаживать данный системный вызов (настраивается через `sysctl`). Для вывода сообщений используются макросы `LMSG` и `ARGS`. Они применяются для форматирования строк вывода с целью создания единообразных отладочных сообщений. [[conclusion]] == Заключение [[results]] === Результаты По состоянию на апрель 2007 года уровень эмуляции Linux(R) способен достаточно хорошо эмулировать ядро Linux(R) 2.6.16. Оставшиеся проблемы касаются фьютексов, незавершённого семейства системных вызовов *at, проблематичной доставки сигналов, отсутствия `epoll` и `inotify`, а также, вероятно, некоторых ошибок, которые мы ещё не обнаружили. Несмотря на это, мы способны запускать практически все программы Linux(R), включённые в Коллекцию портов FreeBSD, с Fedora Core 4 на ядре 2.6.16, а также есть некоторые предварительные сообщения об успешной работе с Fedora Core 6 на ядре 2.6.16. Недавно был добавлен linux_base Fedora Core 6, что позволило провести дополнительные тестирования уровня эмуляции и дало нам больше подсказок, куда следует направить усилия для реализации недостающих функций. Мы можем запускать наиболее популярные приложения, такие как package:www/linux-firefox[], package:net-im/skype[], и некоторые игры из Коллекции портов. Некоторые программы демонстрируют некорректное поведение при эмуляции 2.6, но это в настоящее время исследуется, и, надеемся, скоро будет исправлено. Единственное крупное приложение, которое, как известно, не работает, — это Linux(R) Java(TM) Development Kit, и это связано с требованием функции `epoll`, которая не имеет прямого отношения к ядру Linux(R) 2.6. Мы надеемся включить эмуляцию 2.6.16 по умолчанию через некоторое время после выхода FreeBSD 7.0, по крайней мере, чтобы открыть части эмуляции 2.6 для более широкого тестирования. Как только это будет сделано, мы сможем перейти на Fedora Core 6 linux_base, что является конечной целью. [[future-work]] === Будущие работы Будущая работа должна быть сосредоточена на исправлении оставшихся проблем с фьютексами, реализации оставшихся системных вызовов семейства *at, исправлении доставки сигналов и, возможно, реализации механизмов `epoll` и `inotify`. Мы надеемся вскоре добиться безупречной работы наиболее важных программ, чтобы можно было по умолчанию переключиться на эмуляцию 2.6 и сделать Fedora Core 6 базовой версией linux_base, поскольку используемая в настоящее время Fedora Core 4 больше не поддерживается. Другая возможная цель — поделиться нашим кодом с NetBSD и DragonflyBSD. NetBSD имеет некоторую поддержку эмуляции 2.6, но она далека от завершения и не была должным образом протестирована. DragonflyBSD выразила некоторую заинтересованность в переносе улучшений версии 2.6. В целом, по мере развития Linux(R) мы хотели бы идти в ногу с их разработкой, реализуя новые системные вызовы. В первую очередь на ум приходит `splice`. Некоторые уже реализованные системные вызовы также неоптимальны, например `mremap` и другие. Также можно внести некоторые улучшения производительности, такие как более детальная блокировка и другие. [[team]] === Команда Я сотрудничал в этом проекте с (в алфавитном порядке): * `{jhb}` * `{kib}` * Emmanuel Dreyfus * Scot Hetzel * `{jkim}` * `{netchild}` * `{ssouhlal}` * Li Xiao * `{davidxu}` Я хотел бы поблагодарить всех этих людей за их советы, рецензирование кода и общую поддержку. [[literatures]] == Литература . Marshall Kirk McKusick - George V. Neville-Neil. Design and Implementation of the FreeBSD operating system. Addison-Wesley, 2005 год. . https://tldp.org[https://tldp.org] . https://www.kernel.org[https://www.kernel.org] diff --git a/documentation/content/ru/articles/linux-emulation/_index.po b/documentation/content/ru/articles/linux-emulation/_index.po index 43546c6861..7ce32d7274 100644 --- a/documentation/content/ru/articles/linux-emulation/_index.po +++ b/documentation/content/ru/articles/linux-emulation/_index.po @@ -1,4414 +1,4414 @@ # SOME DESCRIPTIVE TITLE # Copyright (C) YEAR The FreeBSD Project # This file is distributed under the same license as the FreeBSD Documentation package. # Vladlen Popolitov , 2025, 2026. msgid "" msgstr "" "Project-Id-Version: FreeBSD Documentation VERSION\n" "POT-Creation-Date: 2025-11-08 16:17+0000\n" -"PO-Revision-Date: 2026-03-08 09:11+0000\n" +"PO-Revision-Date: 2026-04-05 04:45+0000\n" "Last-Translator: Vladlen Popolitov \n" "Language-Team: Russian \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "X-Generator: Weblate 4.17\n" #. type: YAML Front Matter: description #: documentation/content/en/articles/linux-emulation/_index.adoc:1 #, no-wrap msgid "A technical description about the internals of the Linux emulation layer in FreeBSD" msgstr "Техническое описание внутреннего устройства слоя эмуляции Linux в FreeBSD" #. type: YAML Front Matter: title #: documentation/content/en/articles/linux-emulation/_index.adoc:1 #, no-wrap msgid "Linux® emulation in FreeBSD" msgstr "Эмуляция Linux® в FreeBSD" #. type: Title = #: documentation/content/en/articles/linux-emulation/_index.adoc:11 #, no-wrap msgid "Linux(R) emulation in FreeBSD" msgstr "Эмуляция Linux(R) в FreeBSD" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:44 msgid "Abstract" msgstr "Аннотация" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:54 msgid "" "This masters thesis deals with updating the Linux(R) emulation layer (the so " "called _Linuxulator_). The task was to update the layer to match the " "functionality of Linux(R) 2.6. As a reference implementation, the Linux(R) " "2.6.16 kernel was chosen. The concept is loosely based on the NetBSD " "implementation. Most of the work was done in the summer of 2006 as a part " "of the Google Summer of Code students program. The focus was on bringing " "the _NPTL_ (new POSIX(R) thread library) support into the emulation layer, " "including _TLS_ (thread local storage), _futexes_ (fast user space mutexes), " "_PID mangling_, and some other minor things. Many small problems were " "identified and fixed in the process. My work was integrated into the main " "FreeBSD source repository and will be shipped in the upcoming 7.0R release. " "We, the emulation development team, are working on making the Linux(R) 2.6 " "emulation the default emulation layer in FreeBSD." msgstr "" "Эта магистерская диссертация посвящена обновлению слоя эмуляции Linux(R) " "(так называемого _Linuxulator_). Задача состояла в обновлении слоя для " "соответствия функциональности Linux(R) 2.6. В качестве эталонной реализации " "было выбрано ядро Linux(R) 2.6.16. Концепция основана на реализации NetBSD. " "Большая часть работы была выполнена летом 2006 года в рамках программы " "Google Summer of Code для студентов. Основное внимание уделялось добавлению " "поддержки _NPTL_ (новой библиотеки потоков POSIX(R)) в слой эмуляции, " "включая _TLS_ (локальное хранилище потоков), _фьютексы (futex)_ (быстрые " "мьютексы в пользовательском пространстве), _PID mangling_ и некоторые другие " "второстепенные аспекты. В процессе было выявлено и исправлено множество " "мелких проблем. Моя работа была интегрирована в основной репозиторий " "исходного кода FreeBSD и войдет в предстоящий релиз 7.0R. Мы, команда " "разработчиков эмуляции, работаем над тем, чтобы сделать эмуляцию Linux(R) " "2.6 стандартным слоем эмуляции в FreeBSD." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:56 msgid "'''" msgstr "'''" #. type: Title == #: documentation/content/en/articles/linux-emulation/_index.adoc:60 #, no-wrap msgid "Introduction" msgstr "Введение" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:67 msgid "" "In the last few years the open source UNIX(R) based operating systems " "started to be widely deployed on server and client machines. Among these " "operating systems I would like to point out two: FreeBSD, for its BSD " "heritage, time proven code base and many interesting features and Linux(R) " "for its wide user base, enthusiastic open developer community and support " "from large companies. FreeBSD tends to be used on server class machines " "serving heavy duty networking tasks with less usage on desktop class " "machines for ordinary users. While Linux(R) has the same usage on servers, " "but it is used much more by home based users. This leads to a situation " "where there are many binary only programs available for Linux(R) that lack " "support for FreeBSD." msgstr "" "В последние несколько лет операционные системы с открытым исходным кодом на " "основе UNIX(R) начали широко использоваться на серверных и клиентских " "машинах. Среди этих операционных систем я хотел бы выделить две: FreeBSD — " "за наследие BSD, проверенную временем кодобазу и множество интересных " "возможностей, и Linux(R) — за широкую пользовательскую базу, активное " "сообщество разработчиков и поддержку крупных компаний. FreeBSD чаще " "используется на серверных машинах, выполняющих сложные сетевые задачи, и " "реже — на настольных компьютерах обычных пользователей. В то время как " "Linux(R) также применяется на серверах, он гораздо популярнее среди домашних " "пользователей. Это приводит к ситуации, когда для Linux(R) доступно " "множество проприетарных программ, которые не поддерживают FreeBSD." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:69 msgid "" "Naturally, a need for the ability to run Linux(R) binaries on a FreeBSD " "system arises and this is what this thesis deals with: the emulation of the " "Linux(R) kernel in the FreeBSD operating system." msgstr "" "Естественно, возникает необходимость в возможности запуска Linux(R) " "бинарников в системе FreeBSD, и именно этому посвящена данная работа: " "эмуляции ядра Linux(R) в операционной системе FreeBSD." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:72 msgid "" "During the Summer of 2006 Google Inc. sponsored a project which focused on " "extending the Linux(R) emulation layer (the so called Linuxulator) in " "FreeBSD to include Linux(R) 2.6 facilities. This thesis is written as a " "part of this project." msgstr "" "Летом 2006 года компания Google Inc. спонсировала проект, направленный на " "расширение слоя эмуляции Linux(R) (так называемого Linuxulator) в FreeBSD " "для включения возможностей Linux(R) 2.6. Данная диссертация написана в " "рамках этого проекта." #. type: Title == #: documentation/content/en/articles/linux-emulation/_index.adoc:74 #, no-wrap msgid "A look inside..." msgstr "Взгляд изнутри..." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:80 msgid "" "In this section we are going to describe every operating system in " "question. How they deal with syscalls, trapframes etc., all the low-level " "stuff. We also describe the way they understand common UNIX(R) primitives " "like what a PID is, what a thread is, etc. In the third subsection we talk " "about how UNIX(R) on UNIX(R) emulation could be done in general." msgstr "" "В этом разделе мы рассмотрим каждую из рассматриваемых операционных систем. " "Как они работают с системными вызовами, фреймами прерываний и другими " "низкоуровневыми аспектами. Также мы опишем, как они интерпретируют общие " "примитивы UNIX(R), такие как PID, потоки и т. д. В третьем подразделе мы " "поговорим о том, как в целом может быть реализована эмуляция UNIX(R) на " "UNIX(R)." #. type: Title === #: documentation/content/en/articles/linux-emulation/_index.adoc:82 #, no-wrap msgid "What is UNIX(R)" msgstr "Что такое UNIX(R)" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:94 msgid "" "UNIX(R) is an operating system with a long history that has influenced " "almost every other operating system currently in use. Starting in the " "1960s, its development continues to this day (although in different " "projects). UNIX(R) development soon forked into two main ways: the BSDs and " "System III/V families. They mutually influenced themselves by growing a " "common UNIX(R) standard. Among the contributions originated in BSD we can " "name virtual memory, TCP/IP networking, FFS, and many others. The System V " "branch contributed to SysV interprocess communication primitives, copy-on-" "write, etc. UNIX(R) itself does not exist any more but its ideas have been " "used by many other operating systems world wide thus forming the so called " "UNIX(R)-like operating systems. These days the most influential ones are " "Linux(R), Solaris, and possibly (to some extent) FreeBSD. There are in-" "company UNIX(R) derivatives (AIX, HP-UX etc.), but these have been more and " "more migrated to the aforementioned systems. Let us summarize typical " "UNIX(R) characteristics." msgstr "" "UNIX(R) — это операционная система с долгой историей, которая повлияла почти " "на все остальные операционные системы, используемые в настоящее время. " "Начиная с 1960-х годов, её разработка продолжается и по сей день (хотя в " "разных проектах). Вскоре развитие UNIX(R) разделилось на два основных " "направления: семейства BSD и System III/V. Они взаимно влияли друг на друга, " "формируя общий стандарт UNIX(R). Среди вклада, возникшего в BSD, можно " "назвать виртуальную память, сетевой стек TCP/IP, FFS и многие другие. Ветка " "System V внесла свой вклад в примитивы межпроцессного взаимодействия SysV, " "копирование при записи и т. д. Самого UNIX(R) больше не существует, но его " "идеи были использованы многими другими операционными системами по всему " "миру, образовав так называемые UNIX(R)-подобные операционные системы. В наши " "дни наиболее влиятельными из них являются Linux(R), Solaris и, возможно (в " "некоторой степени), FreeBSD. Существуют корпоративные производные UNIX(R) " "(AIX, HP-UX и т. д.), но они всё больше мигрируют на упомянутые системы. " "Давайте подведём итог типичным характеристикам UNIX(R)." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:96 #: documentation/content/en/articles/linux-emulation/_index.adoc:187 #: documentation/content/en/articles/linux-emulation/_index.adoc:279 #, no-wrap msgid "Technical details" msgstr "Технические детали" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:104 msgid "" "Every running program constitutes a process that represents a state of the " "computation. Running process is divided between kernel-space and user-" "space. Some operations can be done only from kernel space (dealing with " "hardware etc.), but the process should spend most of its lifetime in the " "user space. The kernel is where the management of the processes, hardware, " "and low-level details take place. The kernel provides a standard unified " "UNIX(R) API to the user space. The most important ones are covered below." msgstr "" "Каждая запущенная программа представляет собой процесс, который отражает " "состояние вычислений. Выполняющийся процесс разделяется между пространством " "ядра и пользовательским пространством. Некоторые операции могут выполняться " "только из пространства ядра (например, работа с оборудованием), но процесс " "должен проводить большую часть своего времени в пользовательском " "пространстве. Ядро — это место, где происходит управление процессами, " "оборудованием и низкоуровневыми деталями. Ядро предоставляет стандартный " "унифицированный UNIX(R) API для пользовательского пространства. Наиболее " "важные из них рассмотрены ниже." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:106 #, no-wrap msgid "Communication between kernel and user space process" msgstr "Обмен данными между ядром и пользовательским процессом" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:114 msgid "" "Common UNIX(R) API defines a syscall as a way to issue commands from a user " "space process to the kernel. The most common implementation is either by " "using an interrupt or specialized instruction (think of `SYSENTER`/`SYSCALL` " "instructions for ia32). Syscalls are defined by a number. For example in " "FreeBSD, the syscall number 85 is the man:swapon[2] syscall and the syscall " "number 132 is man:mkfifo[2]. Some syscalls need parameters, which are " "passed from the user-space to the kernel-space in various ways " "(implementation dependent). Syscalls are synchronous." msgstr "" "Общий API UNIX(R) определяет системный вызов как способ передачи команд из " "пользовательского процесса ядру. Наиболее распространённая реализация " "использует либо прерывание, либо специализированную инструкцию (например, " "инструкции `SYSENTER`/`SYSCALL` для ia32). Системные вызовы определяются по " "номеру. Например, в FreeBSD системный вызов номер 85 — это man:swapon[2], а " "номер 132 — man:mkfifo[2]. Некоторые системные вызовы требуют параметров, " "которые передаются из пользовательского пространства в пространство ядра " "различными способами (зависит от реализации). Системные вызовы являются " "синхронными." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:118 msgid "" "Another possible way to communicate is by using a _trap_. Traps occur " "asynchronously after some event occurs (division by zero, page fault etc.). " "A trap can be transparent for a process (page fault) or can result in a " "reaction like sending a _signal_ (division by zero)." msgstr "" "Еще один возможный способ взаимодействия — использование _прерывания_. " "Прерывания происходят асинхронно после возникновения определённого события (" "деление на ноль, ошибка страницы и т.д.). Прерывание может быть прозрачным " "для процесса (ошибка страницы) или привести к реакции, например, отправке " "_сигнала_ (деление на ноль)." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:120 #, no-wrap msgid "Communication between processes" msgstr "Обмен данными между процессами" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:125 msgid "" "There are other APIs (System V IPC, shared memory etc.) but the single most " "important API is signal. Signals are sent by processes or by the kernel and " "received by processes. Some signals can be ignored or handled by a user " "supplied routine, some result in a predefined action that cannot be altered " "or ignored." msgstr "" "Существуют другие API (System V IPC, разделяемая память и т.д.), но наиболее " "важным API являются сигналы. Сигналы отправляются процессами или ядром и " "принимаются процессами. Некоторые сигналы могут быть проигнорированы или " "обработаны пользовательской процедурой, другие приводят к предопределённому " "действию, которое нельзя изменить или игнорировать." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:127 #, no-wrap msgid "Process management" msgstr "Управление процессами" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:137 msgid "" "Kernel instances are processed first in the system (so called init). Every " "running process can create its identical copy using the man:fork[2] " "syscall. Some slightly modified versions of this syscall were introduced " "but the basic semantic is the same. Every running process can morph into " "some other process using the man:exec[3] syscall. Some modifications of " "this syscall were introduced but all serve the same basic purpose. " "Processes end their lives by calling the man:exit[2] syscall. Every process " "is identified by a unique number called PID. Every process has a defined " "parent (identified by its PID)." msgstr "" "Процессы ядра обрабатываются первыми в системе (так называемый init). Каждый " "запущенный процесс может создать свою идентичную копию, используя системный " "вызов man:fork[2]. Были введены некоторые немного изменённые версии этого " "системного вызова, но базовая семантика остаётся той же. Каждый запущенный " "процесс может превратиться в другой процесс, используя системный вызов man:" "exec[3]. Были введены некоторые модификации этого системного вызова, но все " "они служат одной и той же базовой цели. Процессы завершают своё " "существование, вызывая системный вызов man:exit[2]. Каждый процесс " "идентифицируется уникальным номером, называемым PID. У каждого процесса есть " "определённый родитель (идентифицируемый его PID)." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:139 #, no-wrap msgid "Thread management" msgstr "Управление потоками" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:145 msgid "" "Traditional UNIX(R) does not define any API nor implementation for " "threading, while POSIX(R) defines its threading API but the implementation " "is undefined. Traditionally there were two ways of implementing threads. " "Handling them as separate processes (1:1 threading) or envelope the whole " "thread group in one process and managing the threading in userspace (1:N " "threading). Comparing main features of each approach:" msgstr "" "Традиционный UNIX(R) не определяет никакого API или реализации для потоков, " "в то время как POSIX(R) определяет свой API для потоков, но реализация " "остаётся неопределённой. Традиционно существовало два способа реализации " "потоков: обработка их как отдельных процессов (потоки 1:1) или обёртывание " "всей группы потоков в один процесс с управлением потоками в пользовательском " "пространстве (потоки 1:N). Сравнение основных особенностей каждого подхода:" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:147 msgid "1:1 threading" msgstr "Потоки 1:1" #. type: Bullet: '- ' #: documentation/content/en/articles/linux-emulation/_index.adoc:149 msgid "heavyweight threads" msgstr "тяжеловесные потоки" #. type: Bullet: '- ' #: documentation/content/en/articles/linux-emulation/_index.adoc:150 msgid "" "the scheduling cannot be altered by the user (slightly mitigated by the " "POSIX(R) API)" msgstr "" "планирование не может быть изменено пользователем (частично смягчено " "благодаря POSIX(R) API)" #. type: Bullet: '+ ' #: documentation/content/en/articles/linux-emulation/_index.adoc:151 msgid "no syscall wrapping necessary" msgstr "нет необходимости в обёртке системных вызовов" #. type: Bullet: '+ ' #: documentation/content/en/articles/linux-emulation/_index.adoc:152 msgid "can utilize multiple CPUs" msgstr "может использовать несколько процессоров" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:154 msgid "1:N threading" msgstr "Потоки 1:N" #. type: Bullet: '+ ' #: documentation/content/en/articles/linux-emulation/_index.adoc:156 msgid "lightweight threads" msgstr "легковесные потоки" #. type: Bullet: '+ ' #: documentation/content/en/articles/linux-emulation/_index.adoc:157 msgid "scheduling can be easily altered by the user" msgstr "планирование может быть легко изменено пользователем" #. type: Bullet: '- ' #: documentation/content/en/articles/linux-emulation/_index.adoc:158 msgid "syscalls must be wrapped" msgstr "Системные вызовы должны быть обернуты" #. type: Bullet: '- ' #: documentation/content/en/articles/linux-emulation/_index.adoc:159 msgid "cannot utilize more than one CPU" msgstr "не может использовать более одного CPU" #. type: Title === #: documentation/content/en/articles/linux-emulation/_index.adoc:161 #, no-wrap msgid "What is FreeBSD?" msgstr "Что такое FreeBSD?" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:169 msgid "" "The FreeBSD project is one of the oldest open source operating systems " "currently available for daily use. It is a direct descendant of the genuine " "UNIX(R) so it could be claimed that it is a true UNIX(R) although licensing " "issues do not permit that. The start of the project dates back to the early " "1990's when a crew of fellow BSD users patched the 386BSD operating system. " "Based on this patchkit a new operating system arose named FreeBSD for its " "liberal license. Another group created the NetBSD operating system with " "different goals in mind. We will focus on FreeBSD." msgstr "" "Проект FreeBSD — одна из старейших операционных систем с открытым исходным " "кодом, доступных для повседневного использования. Она является прямым " "потомком оригинальной UNIX(R), поэтому можно утверждать, что это настоящая " "UNIX(R), хотя проблемы с лицензированием не позволяют этого сделать. Начало " "проекта относится к началу 1990-х годов, когда группа пользователей BSD " "создала набор исправлений для операционной системы 386BSD. На основе этого " "набора возникла новая операционная система под названием FreeBSD, получившая " "своё имя благодаря либеральной лицензии. Другая группа создала операционную " "систему NetBSD с другими целями. Мы сосредоточимся на FreeBSD." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:174 msgid "" "FreeBSD is a modern UNIX(R)-based operating system with all the features of " "UNIX(R). Preemptive multitasking, multiuser facilities, TCP/IP networking, " "memory protection, symmetric multiprocessing support, virtual memory with " "merged VM and buffer cache, they are all there. One of the interesting and " "extremely useful features is the ability to emulate other UNIX(R)-like " "operating systems. As of December 2006 and 7-CURRENT development, the " "following emulation functionalities are supported:" msgstr "" "FreeBSD — это современная операционная система на основе UNIX(R), обладающая " "всеми возможностями UNIX(R). Вытесняющая многозадачность, " "многопользовательские функции, сетевые возможности TCP/IP, защита памяти, " "поддержка симметричной многопроцессорности, виртуальная память с " "объединёнными VM и кэшем буфера — всё это присутствует. Одной из интересных " "и чрезвычайно полезных особенностей является возможность эмуляции других " "UNIX(R)-подобных операционных систем. По состоянию на декабрь 2006 года и " "разработку 7-CURRENT поддерживаются следующие функции эмуляции:" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:176 msgid "FreeBSD/i386 emulation on FreeBSD/amd64" msgstr "Совместимость FreeBSD/i386 на FreeBSD/amd64" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:177 msgid "FreeBSD/i386 emulation on FreeBSD/ia64" msgstr "FreeBSD/i386 эмуляция на FreeBSD/ia64" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:178 msgid "Linux(R)-emulation of Linux(R) operating system on FreeBSD" msgstr "Эмуляция Linux(R) операционной системы Linux(R) на FreeBSD" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:179 msgid "NDIS-emulation of Windows networking drivers interface" msgstr "NDIS-эмуляция интерфейса сетевых драйверов Windows" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:180 msgid "NetBSD-emulation of NetBSD operating system" msgstr "NetBSD-эмуляция операционной системы NetBSD" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:181 msgid "PECoff-support for PECoff FreeBSD executables" msgstr "Поддержка PECoff для исполняемых файлов FreeBSD в формате PECoff" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:182 msgid "SVR4-emulation of System V revision 4 UNIX(R)" msgstr "Эмуляция SVR4 System V revision 4 UNIX(R)" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:185 msgid "" "Actively developed emulations are the Linux(R) layer and various FreeBSD-on-" "FreeBSD layers. Others are not supposed to work properly nor be usable " "these days." msgstr "" "Активно разрабатываемые эмуляции — это слой Linux(R) и различные слои " "FreeBSD-on-FreeBSD. Остальные в настоящее время не должны работать корректно " "или быть пригодными к использованию." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:195 msgid "" "FreeBSD is traditional flavor of UNIX(R) in the sense of dividing the run of " "processes into two halves: kernel space and user space run. There are two " "types of process entry to the kernel: a syscall and a trap. There is only " "one way to return. In the subsequent sections we will describe the three " "gates to/from the kernel. The whole description applies to the i386 " "architecture as the Linuxulator only exists there but the concept is similar " "on other architectures. The information was taken from [1] and the source " "code." msgstr "" "FreeBSD — это традиционный вариант UNIX(R) в смысле разделения выполнения " "процессов на две части: выполнение в пространстве ядра и выполнение в " "пространстве пользователя. Существует два типа входа процесса в ядро: " "системный вызов (syscall) и ловушка (trap). Возврат только один. В " "последующих разделах мы опишем три входа/выхода в/из ядра. Всё описание " "относится к архитектуре i386, так как Linuxulator существует только там, но " "концепция схожа на других архитектурах. Информация была взята из [1] и " "исходного кода." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:197 #, no-wrap msgid "System entries" msgstr "Системные записи" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:204 msgid "" "FreeBSD has an abstraction called an execution class loader, which is a " "wedge into the man:execve[2] syscall. This employs a structure `sysentvec`, " "which describes an executable ABI. It contains things like errno " "translation table, signal translation table, various functions to serve " "syscall needs (stack fixup, coredumping, etc.). Every ABI the FreeBSD " "kernel wants to support must define this structure, as it is used later in " "the syscall processing code and at some other places. System entries are " "handled by trap handlers, where we can access both the kernel-space and the " "user-space at once." msgstr "" "В FreeBSD существует абстракция, называемая загрузчиком классов исполнения, " "которая является прослойкой в системном вызове man:execve[2]. Она использует " "структуру `sysentvec`, описывающую ABI исполняемого файла. Эта структура " "содержит такие элементы, как таблицу преобразования errno, таблицу " "преобразования сигналов, различные функции для обработки системных вызовов " "(исправление стека, создание дампов памяти и т.д.). Каждый ABI, который ядро " "FreeBSD поддерживает, должен определять эту структуру, так как она " "используется в дальнейшем в коде обработки системных вызовов и в некоторых " "других местах. Системные вызовы обрабатываются обработчиками прерываний, где " "можно одновременно получить доступ как к пространству ядра, так и к " "пользовательскому пространству." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:206 #: documentation/content/en/articles/linux-emulation/_index.adoc:288 #, no-wrap msgid "Syscalls" msgstr "Системные вызовы" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:209 msgid "" "Syscalls on FreeBSD are issued by executing interrupt `0x80` with register `" "%eax` set to a desired syscall number with arguments passed on the stack." msgstr "" "Системные вызовы в FreeBSD выполняются путем прерывания `0x80` с " "установленным в регистре `%eax` номером нужного системного вызова и " "аргументами, переданными через стек." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:215 msgid "" "When a process issues an interrupt `0x80`, the `int0x80` syscall trap " "handler is issued (defined in [.filename]#sys/i386/i386/exception.s#), which " "prepares arguments (i.e. copies them on to the stack) for a call to a C " "function man:syscall[2] (defined in [.filename]#sys/i386/i386/trap.c#), " "which processes the passed in trapframe. The processing consists of " "preparing the syscall (depending on the `sysvec` entry), determining if the " "syscall is 32-bit or 64-bit one (changes size of the parameters), then the " "parameters are copied, including the syscall. Next, the actual syscall " "function is executed with processing of the return code (special cases for " "`ERESTART` and `EJUSTRETURN` errors). Finally an `userret()` is scheduled, " "switching the process back to the users-pace. The parameters to the actual " "syscall handler are passed in the form of `struct thread *td`, `struct " "syscall args *` arguments where the second parameter is a pointer to the " "copied in structure of parameters." msgstr "" "Когда процесс вызывает прерывание `0x80`, срабатывает обработчик системного " "вызова `int0x80` (определённый в [.filename]#sys/i386/i386/exception.s#), " "который подготавливает аргументы (т.е. копирует их в стек) для вызова " "функции на языке C man:syscall[2] (определённой в [.filename]#sys/i386/i386/" "trap.c#), обрабатывающей переданный фрейм прерывания. Обработка включает " "подготовку системного вызова (в зависимости от записи `sysvec`), определение " "разрядности системного вызова (32-битный или 64-битный, что влияет на размер " "параметров), после чего параметры копируются, включая сам системный вызов. " "Затем выполняется фактическая функция системного вызова с обработкой кода " "возврата (особые случаи для ошибок `ERESTART` и `EJUSTRETURN`). В завершение " "планируется вызов `userret()`, возвращающий процесс в пользовательское " "пространство. Параметры для фактического обработчика системного вызова " "передаются в виде аргументов `struct thread *td`, `struct syscall args *`, " "где второй параметр является указателем на скопированную структуру " "параметров." #. type: Title === #: documentation/content/en/articles/linux-emulation/_index.adoc:217 #: documentation/content/en/articles/linux-emulation/_index.adoc:307 #: documentation/content/en/articles/linux-emulation/_index.adoc:794 #, no-wrap msgid "Traps" msgstr "Ловушки (trap)" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:224 msgid "" "Handling of traps in FreeBSD is similar to the handling of syscalls. " "Whenever a trap occurs, an assembler handler is called. It is chosen " "between alltraps, alltraps with regs pushed or calltrap depending on the " "type of the trap. This handler prepares arguments for a call to a C " "function `trap()` (defined in [.filename]#sys/i386/i386/trap.c#), which then " "processes the occurred trap. After the processing it might send a signal to " "the process and/or exit to userland using `userret()`." msgstr "" "Обработка ловушек в FreeBSD аналогична обработке системных вызовов. При " "возникновении ловушки вызывается обработчик на ассемблере. Он выбирается " "между `alltraps`, `alltraps` с сохранением регистров или `calltrap` в " "зависимости от типа ловушки. Этот обработчик подготавливает аргументы для " "вызова функции на языке C `trap()` (определена в [.filename]#sys/i386/i386/" "trap.c#), которая затем обрабатывает произошедшую ловушку. После обработки " "она может отправить сигнал процессу и/или вернуться в пользовательское " "пространство с помощью `userret()`." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:226 #: documentation/content/en/articles/linux-emulation/_index.adoc:312 #, no-wrap msgid "Exits" msgstr "Выходы" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:230 msgid "" "Exits from kernel to userspace happen using the assembler routine `doreti` " "regardless of whether the kernel was entered via a trap or via a syscall. " "This restores the program status from the stack and returns to the userspace." msgstr "" "Выход из ядра в пользовательское пространство происходит с использованием " "ассемблерной процедуры `doreti`, независимо от того, было ли ядро вызвано " "через ловушку или через системный вызов. Это восстанавливает состояние " "программы из стека и возвращает управление в пользовательское пространство." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:232 #: documentation/content/en/articles/linux-emulation/_index.adoc:318 #, no-wrap msgid "UNIX(R) primitives" msgstr "Примитивы UNIX(R)" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:238 msgid "" "FreeBSD operating system adheres to the traditional UNIX(R) scheme, where " "every process has a unique identification number, the so called _PID_ " "(Process ID). PID numbers are allocated either linearly or randomly ranging " "from `0` to `PID_MAX`. The allocation of PID numbers is done using linear " "searching of PID space. Every thread in a process receives the same PID " "number as result of the man:getpid[2] call." msgstr "" "Операционная система FreeBSD придерживается традиционной схемы UNIX(R), где " "каждый процесс имеет уникальный идентификационный номер, так называемый " "_PID_ (Идентификатор Процесса). Номера PID выделяются либо линейно, либо " "случайным образом в диапазоне от `0` до `PID_MAX`. Распределение номеров PID " "осуществляется с помощью линейного поиска в пространстве PID. Каждый поток в " "процессе получает тот же номер PID в результате вызова man:getpid[2]." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:249 msgid "" "There are currently two ways to implement threading in FreeBSD. The first " "way is M:N threading followed by the 1:1 threading model. The default " "library used is M:N threading (`libpthread`) and you can switch at runtime " "to 1:1 threading (`libthr`). The plan is to switch to 1:1 library by " "default soon. Although those two libraries use the same kernel primitives, " "they are accessed through different API(es). The M:N library uses the " "`kse_*` family of syscalls while the 1:1 library uses the `thr_*` family of " "syscalls. Due to this, there is no general concept of thread ID shared " "between kernel and userspace. Of course, both threading libraries implement " "the pthread thread ID API. Every kernel thread (as described by `struct " "thread`) has td tid identifier but this is not directly accessible from " "userland and solely serves the kernel's needs. It is also used for 1:1 " "threading library as pthread's thread ID but handling of this is internal to " "the library and cannot be relied on." msgstr "" "В настоящее время в FreeBSD существует два способа реализации потоков. " "Первый способ — это M:N потоки, за которым следует модель потоков 1:1. По " "умолчанию используется библиотека M:N (`libpthread`), но во время выполнения " "можно переключиться на потоки 1:1 (`libthr`). Планируется в ближайшее время " "перейти на библиотеку 1:1 по умолчанию. Хотя обе библиотеки используют одни " "и те же примитивы ядра, доступ к ним осуществляется через разные API. " "Библиотека M:N использует семейство системных вызовов `kse_*`, тогда как " "библиотека 1:1 использует семейство `thr_*`. Из-за этого отсутствует общая " "концепция идентификатора потока, разделяемая между ядром и пользовательским " "пространством. Конечно, обе библиотеки реализуют API идентификатора потока " "pthread. У каждого потока ядра (как описано в `struct thread`) есть " "идентификатор td tid, но он недоступен напрямую из пользовательского " "пространства и служит исключительно нуждам ядра. Он также используется в " "библиотеке потоков 1:1 в качестве идентификатора потока pthread, но " "обработка этого идентификатора внутренняя для библиотеки и не может быть " "использована напрямую." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:257 msgid "" "As stated previously there are two implementations of threading in FreeBSD. " "The M:N library divides the work between kernel space and userspace. Thread " "is an entity that gets scheduled in the kernel but it can represent various " "number of userspace threads. M userspace threads get mapped to N kernel " "threads thus saving resources while keeping the ability to exploit " "multiprocessor parallelism. Further information about the implementation " "can be obtained from the man page or [1]. The 1:1 library directly maps a " "userland thread to a kernel thread thus greatly simplifying the scheme. " "None of these designs implement a fairness mechanism (such a mechanism was " "implemented but it was removed recently because it caused serious slowdown " "and made the code more difficult to deal with)." msgstr "" "Как упоминалось ранее, в FreeBSD существуют две реализации потоков. " "Библиотека M:N разделяет работу между пространством ядра и пользовательским " "пространством. Поток — это сущность, которая планируется в ядре, но может " "представлять различное количество пользовательских потоков. M " "пользовательских потоков отображаются на N потоков ядра, что позволяет " "экономить ресурсы, сохраняя при этом возможность использовать преимущества " "многопроцессорного параллелизма. Дополнительную информацию о реализации " "можно получить из man-страницы или [1]. Библиотека 1:1 напрямую отображает " "пользовательский поток на поток ядра, что значительно упрощает схему. Ни " "одна из этих реализаций не включает механизм справедливости (такой механизм " "был реализован, но недавно удалён, поскольку вызывал серьёзное замедление и " "усложнял работу с кодом)." #. type: Title === #: documentation/content/en/articles/linux-emulation/_index.adoc:259 #, no-wrap msgid "What is Linux(R)" msgstr "Что такое Linux(R)" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:263 msgid "" "Linux(R) is a UNIX(R)-like kernel originally developed by Linus Torvalds, " "and now being contributed to by a massive crowd of programmers all around " "the world. From its mere beginnings to today, with wide support from " "companies such as IBM or Google, Linux(R) is being associated with its fast " "development pace, full hardware support and benevolent dictator model of " "organization." msgstr "" "Linux(R) — это UNIX(R)-подобное ядро, изначально разработанное Линусом " "Торвальдсом, а сейчас развиваемое множеством программистов по всему миру. От " "своих скромных начал до сегодняшнего дня, при широкой поддержке таких " "компаний, как IBM или Google, Linux(R) ассоциируется с быстрым темпом " "разработки, полной поддержкой оборудования и моделью организации по принципу " "\"доброжелательного диктатора\"." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:267 msgid "" "Linux(R) development started in 1991 as a hobbyist project at University of " "Helsinki in Finland. Since then it has obtained all the features of a " "modern UNIX(R)-like OS: multiprocessing, multiuser support, virtual memory, " "networking, basically everything is there. There are also highly advanced " "features like virtualization etc." msgstr "" "Разработка Linux(R) началась в 1991 году как любительский проект в " "Университете Хельсинки, Финляндия. С тех пор она приобрела все черты " "современной ОС, подобной UNIX(R): многопроцессорность, поддержка " "многопользовательского режима, виртуальная память, сетевое взаимодействие — " "в общем, всё необходимое. Также присутствуют высокоуровневые функции, такие " "как виртуализация и т. д." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:270 msgid "" "As of 2006 Linux(R) seems to be the most widely used open source operating " "system with support from independent software vendors like Oracle, " "RealNetworks, Adobe, etc. Most of the commercial software distributed for " "Linux(R) can only be obtained in a binary form so recompilation for other " "operating systems is impossible." msgstr "" "В 2006 году Linux(R), похоже, был наиболее широко используемой открытой " "операционной системой с поддержкой независимых поставщиков программного " "обеспечения, таких как Oracle, RealNetworks, Adobe и других. Большая часть " "коммерческого программного обеспечения, распространяемого для Linux(R), " "доступна только в бинарном виде, поэтому перекомпиляция для других " "операционных систем невозможна." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:275 msgid "" "Most of the Linux(R) development happens in a Git version control system. " "Git is a distributed system so there is no central source of the Linux(R) " "code, but some branches are considered prominent and official. The version " "number scheme implemented by Linux(R) consists of four numbers A.B.C.D. " "Currently development happens in 2.6.C.D, where C represents major version, " "where new features are added or changed while D is a minor version for " "bugfixes only." msgstr "" "Большая часть разработки Linux(R) происходит в системе контроля версий Git. " "Git — это распределённая система, поэтому нет централизованного источника " "кода Linux(R), но некоторые ветви считаются основными и официальными. Схема " "нумерации версий, используемая в Linux(R), состоит из четырёх чисел: A.B.C." "D. В настоящее время разработка ведётся в ветке 2.6.C.D, где C обозначает " "мажорную версию, в которую добавляются или изменяются функции, а D — " "минорную версию, предназначенную только для исправления ошибок." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:277 msgid "More information can be obtained from [3]." msgstr "Дополнительную информацию можно получить из [3]." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:286 msgid "" "Linux(R) follows the traditional UNIX(R) scheme of dividing the run of a " "process in two halves: the kernel and user space. The kernel can be entered " "in two ways: via a trap or via a syscall. The return is handled only in one " "way. The further description applies to Linux(R) 2.6 on the i386(TM) " "architecture. This information was taken from [2]." msgstr "" "Linux(R) следует традиционной схеме UNIX(R), разделяя выполнение процесса на " "две части: ядро и пользовательское пространство. Ядро может быть вызвано " "двумя способами: через ловушку (trap) или через системный вызов. Возврат " "осуществляется только одним способом. Далее описание относится к Linux(R) " "2.6 на архитектуре i386(TM). Эта информация взята из [2]." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:296 msgid "" "Syscalls in Linux(R) are performed (in userspace) using `syscallX` macros " "where X substitutes a number representing the number of parameters of the " "given syscall. This macro translates to a code that loads `%eax` register " "with a number of the syscall and executes interrupt `0x80`. After this " "syscall return is called, which translates negative return values to " "positive `errno` values and sets `res` to `-1` in case of an error. " "Whenever the interrupt `0x80` is called the process enters the kernel in " "system call trap handler. This routine saves all registers on the stack and " "calls the selected syscall entry. Note that the Linux(R) calling convention " "expects parameters to the syscall to be passed via registers as shown here:" msgstr "" "Системные вызовы в Linux(R) выполняются (в пользовательском пространстве) с " "использованием макросов `syscallX`, где X заменяется числом, представляющим " "количество параметров данного системного вызова. Этот макрос преобразуется в " "код, который загружает регистр `%eax` номером системного вызова и выполняет " "прерывание `0x80`. После этого вызывается возврат из системного вызова, " "который преобразует отрицательные значения возврата в положительные значения " "`errno` и устанавливает `res` в `-1` в случае ошибки. При вызове прерывания " "`0x80` процесс переходит в ядро в обработчик ловушки системного вызова. Эта " "процедура сохраняет все регистры в стеке и вызывает выбранную точку входа " "системного вызова. Обратите внимание, что соглашение о вызовах Linux(R) " "предполагает передачу параметров системного вызова через регистры, как " "показано здесь:" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:298 msgid "parameter -> `%ebx`" msgstr "параметр -> `%ebx`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:299 msgid "parameter -> `%ecx`" msgstr "параметр -> `%ecx`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:300 msgid "parameter -> `%edx`" msgstr "параметр -> `%edx`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:301 msgid "parameter -> `%esi`" msgstr "параметр -> `%esi`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:302 msgid "parameter -> `%edi`" msgstr "параметр -> `%edi`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:303 msgid "parameter -> `%ebp`" msgstr "параметр -> `%ebp`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:305 msgid "" "There are some exceptions to this, where Linux(R) uses different calling " "convention (most notably the `clone` syscall)." msgstr "" "Существуют некоторые исключения из этого правила, где Linux(R) использует " "другие соглашения о вызовах (наиболее примечателен системный вызов `clone`)." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:310 msgid "" "The trap handlers are introduced in [.filename]#arch/i386/kernel/traps.c# " "and most of these handlers live in [.filename]#arch/i386/kernel/entry.S#, " "where handling of the traps happens." msgstr "" "Обработчики ловушек представлены в файле [.filename]#arch/i386/kernel/traps." "c#, а большинство этих обработчиков находятся в [.filename]#arch/i386/kernel/" "entry.S#, где происходит обработка ловушек." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:316 msgid "" "Return from the syscall is managed by syscall man:exit[3], which checks for " "the process having unfinished work, then checks whether we used user-" "supplied selectors. If this happens stack fixing is applied and finally the " "registers are restored from the stack and the process returns to the " "userspace." msgstr "" "Возврат из системного вызова обрабатывается функцией `syscall man:exit[3]`, " "которая проверяет, есть ли у процесса незавершённые задачи, затем проверяет, " "использовались ли селекторы, предоставленные пользователем. Если это " "произошло, применяется исправление стека, и, наконец, регистры " "восстанавливаются из стека, а процесс возвращается в пользовательское " "пространство." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:327 msgid "" "In the 2.6 version, the Linux(R) operating system redefined some of the " "traditional UNIX(R) primitives, notably PID, TID and thread. PID is defined " "not to be unique for every process, so for some processes (threads) man:" "getppid[2] returns the same value. Unique identification of process is " "provided by TID. This is because _NPTL_ (New POSIX(R) Thread Library) " "defines threads to be normal processes (so called 1:1 threading). Spawning " "a new process in Linux(R) 2.6 happens using the `clone` syscall (fork " "variants are reimplemented using it). This clone syscall defines a set of " "flags that affect behavior of the cloning process regarding thread " "implementation. The semantic is a bit fuzzy as there is no single flag " "telling the syscall to create a thread." msgstr "" "В версии 2.6 операционная система Linux(R) переопределила некоторые " "традиционные примитивы UNIX(R), в частности PID, TID и поток. PID " "определяется не как уникальный для каждого процесса, поэтому для некоторых " "процессов (потоков) man:getppid[2] возвращает одинаковое значение. " "Уникальная идентификация процесса обеспечивается TID. Это связано с тем, что " "_NPTL_ (New POSIX(R) Thread Library) определяет потоки как обычные процессы " "(так называемая модель 1:1). Создание нового процесса в Linux(R) 2.6 " "происходит с использованием системного вызова `clone` (варианты fork " "перереализованы с его использованием). Этот системный вызов clone определяет " "набор флагов, которые влияют на поведение процесса клонирования в отношении " "реализации потоков. Семантика немного размыта, так как нет единого флага, " "указывающего системному вызову создать поток." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:329 msgid "Implemented clone flags are:" msgstr "Реализованные флаги клонирования:" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:331 msgid "`CLONE_VM` - processes share their memory space" msgstr "`CLONE_VM` - процессы разделяют общее адресное пространство" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:332 msgid "`CLONE_FS` - share umask, cwd and namespace" msgstr "" "`CLONE_FS` — совместно использовать umask, текущий рабочий каталог и " "пространство имён" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:333 msgid "`CLONE_FILES` - share open files" msgstr "`CLONE_FILES` - совместно использовать открытые файлы" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:334 msgid "`CLONE_SIGHAND` - share signal handlers and blocked signals" msgstr "" "`CLONE_SIGHAND` - разделять обработчики сигналов и заблокированные сигналы" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:335 msgid "`CLONE_PARENT` - share parent" msgstr "`CLONE_PARENT` - использовать один процесс к качестве родительского" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:336 msgid "`CLONE_THREAD` - be thread (further explanation below)" msgstr "`CLONE_THREAD` — быть потоком (дальнейшие пояснения ниже)" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:337 msgid "`CLONE_NEWNS` - new namespace" msgstr "`CLONE_NEWNS` - новое пространство имен" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:338 msgid "`CLONE_SYSVSEM` - share SysV undo structures" msgstr "`CLONE_SYSVSEM` - совместное использование структур отмены SysV" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:339 msgid "`CLONE_SETTLS` - setup TLS at supplied address" msgstr "`CLONE_SETTLS` - настройка TLS по указанному адресу" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:340 msgid "`CLONE_PARENT_SETTID` - set TID in the parent" msgstr "`CLONE_PARENT_SETTID` - установить TID в родителе" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:341 msgid "`CLONE_CHILD_CLEARTID` - clear TID in the child" msgstr "`CLONE_CHILD_CLEARTID` - очистить TID в дочернем процессе" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:342 msgid "`CLONE_CHILD_SETTID` - set TID in the child" msgstr "`CLONE_CHILD_SETTID` - установить TID в дочернем процессе" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:348 msgid "" "`CLONE_PARENT` sets the real parent to the parent of the caller. This is " "useful for threads because if thread A creates thread B we want thread B to " "be parented to the parent of the whole thread group. `CLONE_THREAD` does " "exactly the same thing as `CLONE_PARENT`, `CLONE_VM` and `CLONE_SIGHAND`, " "rewrites PID to be the same as PID of the caller, sets exit signal to be " "none and enters the thread group. `CLONE_SETTLS` sets up GDT entries for " "TLS handling. The `CLONE_*_*TID` set of flags sets/clears user supplied " "address to TID or 0." msgstr "" "`CLONE_PARENT` устанавливает реального родителя в родителя вызывающего " "процесса. Это полезно для потоков, потому что если поток A создаёт поток B, " "мы хотим, чтобы поток B был привязан к родителю всей группы потоков. " "`CLONE_THREAD` делает то же самое, что `CLONE_PARENT`, `CLONE_VM` и " "`CLONE_SIGHAND`, перезаписывает PID, чтобы он совпадал с PID вызывающего " "процесса, устанавливает сигнал завершения в \"нет\" и входит в группу " "потоков. `CLONE_SETTLS` настраивает записи GDT для обработки TLS. Набор " "флагов `CLONE_*_*TID` устанавливает/сбрасывает предоставленный пользователем " "адрес в TID или 0." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:352 msgid "" "As you can see the `CLONE_THREAD` does most of the work and does not seem to " "fit the scheme very well. The original intention is unclear (even for " "authors, according to comments in the code) but I think originally there was " "one threading flag, which was then parcelled among many other flags but this " "separation was never fully finished. It is also unclear what this partition " "is good for as glibc does not use that so only hand-written use of the clone " "permits a programmer to access this features." msgstr "" "Как видно, `CLONE_THREAD` выполняет большую часть работы и не очень хорошо " "вписывается в схему. Первоначальный замысел неясен (даже для авторов, " "согласно комментариям в коде), но я думаю, изначально был один флаг для " "потоков, который затем был разделён на множество других флагов, но это " "разделение так и не было завершено. Также непонятно, для чего нужно это " "разделение, так как glibc не использует его, и только ручное использование " "clone позволяет программисту получить доступ к этим возможностям." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:355 msgid "" "For non-threaded programs the PID and TID are the same. For threaded " "programs the first thread PID and TID are the same and every created thread " "shares the same PID and gets assigned a unique TID (because `CLONE_THREAD` " "is passed in) also parent is shared for all processes forming this threaded " "program." msgstr "" "Для непоточных программ PID и TID совпадают. Для поточных программ первый " "поток имеет одинаковые PID и TID, а каждый созданный поток разделяет тот же " "PID и получает уникальный TID (поскольку передаётся `CLONE_THREAD`), также " "родительский процесс общий для всех процессов, образующих эту поточную " "программу." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:357 msgid "" "The code that implements man:pthread_create[3] in NPTL defines the clone " "flags like this:" msgstr "" "Код, реализующий man:pthread_create[3] в NPTL, определяет флаги clone " "следующим образом:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:361 #, no-wrap msgid "int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL\n" msgstr "int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL\n" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:363 #, no-wrap msgid " | CLONE_SETTLS | CLONE_PARENT_SETTID\n" msgstr " | CLONE_SETTLS | CLONE_PARENT_SETTID\n" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:366 #, no-wrap msgid "" "| CLONE_CHILD_CLEARTID | CLONE_SYSVSEM\n" "#if __ASSUME_NO_CLONE_DETACHED == 0\n" msgstr "" "| CLONE_CHILD_CLEARTID | CLONE_SYSVSEM\n" "#if __ASSUME_NO_CLONE_DETACHED == 0\n" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:369 #, no-wrap msgid "" "| CLONE_DETACHED\n" "#endif\n" msgstr "" "| CLONE_DETACHED\n" "#endif\n" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:371 #, no-wrap msgid "| 0);\n" msgstr "| 0);\n" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:374 msgid "The `CLONE_SIGNAL` is defined like" msgstr "`CLONE_SIGNAL` определен как" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:378 #, no-wrap msgid "#define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD)\n" msgstr "#define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD)\n" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:381 msgid "the last 0 means no signal is sent when any of the threads exits." msgstr "" "последний 0 означает, что сигнал не отправляется при завершении любого из " "потоков." #. type: Title === #: documentation/content/en/articles/linux-emulation/_index.adoc:383 #, no-wrap msgid "What is emulation" msgstr "Что такое эмуляция" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:388 msgid "" "According to a dictionary definition, emulation is the ability of a program " "or device to imitate another program or device. This is achieved by " "providing the same reaction to a given stimulus as the emulated object. In " "practice, the software world mostly sees three types of emulation - a " "program used to emulate a machine (QEMU, various game console emulators " "etc.), software emulation of a hardware facility (OpenGL emulators, floating " "point units emulation etc.) and operating system emulation (either in kernel " "of the operating system or as a userspace program)." msgstr "" "Согласно словарному определению, эмуляция — это способность программы или " "устройства имитировать другую программу или устройство. Это достигается за " "счёт предоставления той же реакции на заданный стимул, что и у эмулируемого " "объекта. На практике в мире программного обеспечения в основном встречаются " "три типа эмуляции — программа, используемая для эмуляции машины (QEMU, " "различные эмуляторы игровых консолей и т.д.), программная эмуляция " "аппаратного обеспечения (эмуляторы OpenGL, эмуляция блоков плавающей запятой " "и т.д.) и эмуляция операционной системы (либо в ядре операционной системы, " "либо в виде программы пользовательского пространства)." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:395 msgid "" "Emulation is usually used in a place, where using the original component is " "not feasible nor possible at all. For example someone might want to use a " "program developed for a different operating system than they use. Then " "emulation comes in handy. Sometimes there is no other way but to use " "emulation - e.g. when the hardware device you try to use does not exist (yet/" "anymore) then there is no other way but emulation. This happens often when " "porting an operating system to a new (non-existent) platform. Sometimes it " "is just cheaper to emulate." msgstr "" "Эмуляция обычно используется в тех случаях, когда применение оригинального " "компонента невозможно или нецелесообразно. Например, может возникнуть " "необходимость использовать программу, разработанную для другой операционной " "системы. В такой ситуации на помощь приходит эмуляция. Иногда эмуляция — " "единственный возможный вариант, например, когда необходимое аппаратное " "устройство ещё не существует или уже не выпускается. Такое часто происходит " "при переносе операционной системы на новую (ещё не существующую) платформу. " "Иногда эмуляция просто экономически выгоднее." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:407 msgid "" "Looking from an implementation point of view, there are two main approaches " "to the implementation of emulation. You can either emulate the whole thing " "- accepting possible inputs of the original object, maintaining inner state " "and emitting correct output based on the state and/or input. This kind of " "emulation does not require any special conditions and basically can be " "implemented anywhere for any device/program. The drawback is that " "implementing such emulation is quite difficult, time-consuming and error-" "prone. In some cases we can use a simpler approach. Imagine you want to " "emulate a printer that prints from left to right on a printer that prints " "from right to left. It is obvious that there is no need for a complex " "emulation layer but simply reversing of the printed text is sufficient. " "Sometimes the emulating environment is very similar to the emulated one so " "just a thin layer of some translation is necessary to provide fully working " "emulation! As you can see this is much less demanding to implement, so less " "time-consuming and error-prone than the previous approach. But the " "necessary condition is that the two environments must be similar enough. " "The third approach combines the two previous. Most of the time the objects " "do not provide the same capabilities so in a case of emulating the more " "powerful one on the less powerful we have to emulate the missing features " "with full emulation described above." msgstr "" "С точки зрения реализации, существует два основных подхода к эмуляции. Вы " "можете либо эмулировать всё целиком — принимать возможные входные данные " "исходного объекта, поддерживать внутреннее состояние и выдавать корректные " "выходные данные на основе состояния и/или входных данных. Такой вид эмуляции " "не требует каких-либо специальных условий и, в принципе, может быть " "реализован где угодно для любого устройства/программы. Недостаток в том, что " "реализация такой эмуляции довольно сложна, трудоёмка и подвержена ошибкам. В " "некоторых случаях можно использовать более простой подход. Представьте, что " "вы хотите эмулировать принтер, печатающий слева направо, на принтере, " "который печатает справа налево. Очевидно, что нет необходимости в сложном " "слое эмуляции — достаточно просто перевернуть печатаемый текст. Иногда " "эмулирующая среда очень похожа на эмулируемую, и тогда достаточно тонкого " "слоя преобразования для обеспечения полностью рабочей эмуляции! Как видите, " "такой подход гораздо менее требователен к реализации, а значит, менее " "трудоёмок и подвержен ошибкам, чем предыдущий. Однако необходимое условие — " "две среды должны быть достаточно схожи. Третий подход сочетает в себе два " "предыдущих. Чаще всего объекты не предоставляют одинаковые возможности, " "поэтому в случае эмуляции более мощного объекта на менее мощном приходится " "эмулировать отсутствующие функции с помощью полной эмуляции, описанной выше." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:410 msgid "" "This master thesis deals with emulation of UNIX(R) on UNIX(R), which is " "exactly the case, where only a thin layer of translation is sufficient to " "provide full emulation. The UNIX(R) API consists of a set of syscalls, " "which are usually self contained and do not affect some global kernel state." msgstr "" "Эта магистерская диссертация посвящена эмуляции UNIX(R) на UNIX(R), что " "является именно тем случаем, когда достаточно тонкого слоя трансляции для " "обеспечения полной эмуляции. API UNIX(R) состоит из набора системных " "вызовов, которые обычно самодостаточны и не влияют на глобальное состояние " "ядра." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:412 msgid "" "There are a few syscalls that affect inner state but this can be dealt with " "by providing some structures that maintain the extra state." msgstr "" "Существует несколько системных вызовов, которые влияют на внутреннее " "состояние, но это можно решить, предоставив некоторые структуры, " "поддерживающие дополнительное состояние." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:416 msgid "" "No emulation is perfect and emulations tend to lack some parts but this " "usually does not cause any serious drawbacks. Imagine a game console " "emulator that emulates everything but music output. No doubt that the games " "are playable and one can use the emulator. It might not be that comfortable " "as the original game console but its an acceptable compromise between price " "and comfort." msgstr "" "Эмуляция не бывает идеальной, и в эмуляторах часто чего-то не хватает, но " "обычно это не вызывает серьёзных проблем. Представьте эмулятор игровой " "приставки, который эмулирует всё, кроме звука. Без сомнения, игры остаются " "играбельными, и эмулятором можно пользоваться. Возможно, это не так " "комфортно, как оригинальная приставка, но это приемлемый компромисс между " "ценой и удобством." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:420 msgid "" "The same goes with the UNIX(R) API. Most programs can live with a very " "limited set of syscalls working. Those syscalls tend to be the oldest ones " "(man:read[2]/man:write[2], man:fork[2] family, man:signal[3] handling, man:" "exit[3], man:socket[2] API) hence it is easy to emulate because their " "semantics is shared among all UNIX(R)es, which exist todays." msgstr "" "То же самое касается UNIX(R) API. Большинство программ могут работать с " "очень ограниченным набором системных вызовов. Эти вызовы, как правило, " "являются самыми старыми (man:read[2]/man:write[2], семейство man:fork[2], " "обработка man:signal[3], man:exit[3], API man:socket[2]), поэтому их легко " "эмулировать, поскольку их семантика одинакова во всех современных UNIX(R)-" "подобных системах." #. type: Title == #: documentation/content/en/articles/linux-emulation/_index.adoc:422 #, no-wrap msgid "Emulation" msgstr "Эмуляция" #. type: Title === #: documentation/content/en/articles/linux-emulation/_index.adoc:424 #, no-wrap msgid "How emulation works in FreeBSD" msgstr "Как работает эмуляция в FreeBSD" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:429 msgid "" "As stated earlier, FreeBSD supports running binaries from several other " "UNIX(R)es. This works because FreeBSD has an abstraction called the " "execution class loader. This wedges into the man:execve[2] syscall, so when " "man:execve[2] is about to execute a binary it examines its type." msgstr "" "Как упоминалось ранее, FreeBSD поддерживает выполнение бинарных файлов из " "нескольких других UNIX(R)-подобных систем. Это возможно благодаря наличию в " "FreeBSD абстракции, называемой загрузчик классов исполнения. Он " "интегрируется в системный вызов man:execve[2], поэтому когда man:execve[2] " "собирается выполнить бинарный файл, он анализирует его тип." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:435 msgid "" "There are basically two types of binaries in FreeBSD. Shell-like text " "scripts which are identified by `#!` as their first two characters and " "normal (typically _ELF_) binaries, which are a representation of a compiled " "executable object. The vast majority (one could say all of them) of " "binaries in FreeBSD are from type ELF. ELF files contain a header, which " "specifies the OS ABI for this ELF file. By reading this information, the " "operating system can accurately determine what type of binary the given file " "is." msgstr "" "В FreeBSD существуют два основных типа исполняемых файлов. Текстовые " "скрипты, подобные shell-скриптам, которые идентифицируются по первым двум " "символам `#!`, и обычные (как правило, _ELF_) бинарные файлы, представляющие " "собой скомпилированные исполняемые объекты. Подавляющее большинство (можно " "сказать, все) исполняемых файлов в FreeBSD относятся к типу ELF. Файлы ELF " "содержат заголовок, который определяет ABI операционной системы для данного " "ELF-файла. Считывая эту информацию, операционная система может точно " "определить, к какому типу относится данный исполняемый файл." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:441 msgid "" "Every OS ABI must be registered in the FreeBSD kernel. This applies to the " "FreeBSD native OS ABI, as well. So when man:execve[2] executes a binary it " "iterates through the list of registered APIs and when it finds the right one " "it starts to use the information contained in the OS ABI description (its " "syscall table, `errno` translation table, etc.). So every time the process " "calls a syscall, it uses its own set of syscalls instead of some global " "one. This effectively provides a very elegant and easy way of supporting " "execution of various binary formats." msgstr "" "Каждый ABI ОС должен быть зарегистрирован в ядре FreeBSD. Это относится и к " "родному ABI ОС FreeBSD. Таким образом, когда man:execve[2] выполняет " "двоичный файл, он перебирает список зарегистрированных API, и когда находит " "подходящий, начинает использовать информацию, содержащуюся в описании ABI ОС " "(его таблицу системных вызовов, таблицу преобразования `errno` и т.д.). " "Таким образом, каждый раз, когда процесс вызывает системный вызов, он " "использует свой собственный набор системных вызовов вместо какого-либо " "глобального. Это обеспечивает очень элегантный и простой способ поддержки " "выполнения различных двоичных форматов." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:446 msgid "" "The nature of emulation of different OSes (and also some other subsystems) " "led developers to invite a handler event mechanism. There are various " "places in the kernel, where a list of event handlers are called. Every " "subsystem can register an event handler and they are called accordingly. " "For example, when a process exits there is a handler called that possibly " "cleans up whatever the subsystem needs to be cleaned." msgstr "" "Природа эмуляции различных ОС (а также некоторых других подсистем) привела " "разработчиков к внедрению механизма обработчиков событий. В ядре существует " "множество мест, где вызывается список обработчиков событий. Каждая " "подсистема может зарегистрировать обработчик событий, и они вызываются " "соответствующим образом. Например, при завершении процесса вызывается " "обработчик, который может выполнить необходимую очистку для подсистемы." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:448 msgid "" "Those simple facilities provide basically everything that is needed for the " "emulation infrastructure and in fact these are basically the only things " "necessary to implement the Linux(R) emulation layer." msgstr "" "Те простые средства предоставляют практически всё необходимое для " "инфраструктуры эмуляции, и, по сути, это единственное, что требуется для " "реализации слоя эмуляции Linux(R)." #. type: Title === #: documentation/content/en/articles/linux-emulation/_index.adoc:450 #, no-wrap msgid "Common primitives in the FreeBSD kernel" msgstr "Общие примитивы в ядре FreeBSD" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:454 msgid "" "Emulation layers need some support from the operating system. I am going to " "describe some of the supported primitives in the FreeBSD operating system." msgstr "" "Для работы слоев эмуляции требуется некоторая поддержка со стороны " "операционной системы. Я расскажу о некоторых поддерживаемых примитивах в " "операционной системе FreeBSD." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:456 #, no-wrap msgid "Locking primitives" msgstr "Примитивы синхронизации" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:459 msgid "Contributed by: `{attilio}`" msgstr "Добавил: `{attilio}`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:461 msgid "" "The FreeBSD synchronization primitive set is based on the idea to supply a " "rather huge number of different primitives in a way that the better one can " "be used for every particular, appropriate situation." msgstr "" "Примитивы синхронизации FreeBSD основаны на идее предоставления достаточно " "большого количества различных примитивов таким образом, чтобы для каждой " "конкретной подходящей ситуации можно было использовать наилучший." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:463 msgid "" "To a high level point of view you can consider three kinds of " "synchronization primitives in the FreeBSD kernel:" msgstr "" "На высоком уровне можно выделить три вида примитивов синхронизации в ядре " "FreeBSD:" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:465 msgid "atomic operations and memory barriers" msgstr "атомарные операции и барьеры памяти" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:466 msgid "locks" msgstr "блокировки" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:467 msgid "scheduling barriers" msgstr "барьеры планирования" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:470 msgid "" "Below there are descriptions for the 3 families. For every lock, you should " "really check the linked manpage (where possible) for more detailed " "explanations." msgstr "" "Ниже приведены описания для 3 семейств. Для каждой блокировки рекомендуется " "ознакомиться с соответствующей справочной страницей (где это возможно), " "чтобы получить более подробные объяснения." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:472 #, no-wrap msgid "Atomic operations and memory barriers" msgstr "Атомарные операции и барьеры памяти" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:483 msgid "" "Atomic operations are implemented through a set of functions performing " "simple arithmetics on memory operands in an atomic way with respect to " "external events (interrupts, preemption, etc.). Atomic operations can " "guarantee atomicity just on small data types (in the magnitude order of the " "`.long.` architecture C data type), so should be rarely used directly in the " "end-level code, if not only for very simple operations (like flag setting in " "a bitmap, for example). In fact, it is rather simple and common to write " "down a wrong semantic based on just atomic operations (usually referred as " "lock-less). The FreeBSD kernel offers a way to perform atomic operations in " "conjunction with a memory barrier. The memory barriers will guarantee that " "an atomic operation will happen following some specified ordering with " "respect to other memory accesses. For example, if we need that an atomic " "operation happen just after all other pending writes (in terms of " "instructions reordering buffers activities) are completed, we need to " "explicitly use a memory barrier in conjunction to this atomic operation. So " "it is simple to understand why memory barriers play a key role for higher-" "level locks building (just as refcounts, mutexes, etc.). For a detailed " "explanatory on atomic operations, please refer to man:atomic[9]. It is far, " "however, noting that atomic operations (and memory barriers as well) should " "ideally only be used for building front-ending locks (as mutexes)." msgstr "" "Атомарные операции реализуются через набор функций, выполняющих простые " "арифметические действия над операндами в памяти атомарным образом по " "отношению к внешним событиям (прерываниям, вытеснению и т. д.). Атомарные " "операции могут гарантировать атомарность только для небольших типов данных (" "порядка величины типа `.long` в архитектуре C), поэтому их следует редко " "использовать напрямую в конечном коде, разве что для очень простых операций (" "например, установки флага в битовой карте). На самом деле довольно просто и " "часто можно допустить семантическую ошибку, полагаясь только на атомарные " "операции (обычно называемые lock-less). Ядро FreeBSD предоставляет способ " "выполнения атомарных операций в сочетании с барьерами памяти. Барьеры памяти " "гарантируют, что атомарная операция произойдет в определённом порядке " "относительно других обращений к памяти. Например, если нам нужно, чтобы " "атомарная операция выполнилась только после завершения всех ожидающих " "операций записи (с точки зрения переупорядочивания буферов инструкций), нам " "необходимо явно использовать барьер памяти вместе с этой атомарной " "операцией. Таким образом, легко понять, почему барьеры памяти играют " "ключевую роль в построении высокоуровневых блокировок (таких как refcounts, " "мьютексы и т. д.). Для подробного объяснения атомарных операций обратитесь к " "man:atomic[9]. Однако важно отметить, что атомарные операции (и барьеры " "памяти тоже) в идеале должны использоваться только для построения фронтенд-" "блокировок (например, мьютексов)." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:485 #, no-wrap msgid "Refcounts" msgstr "Счетчики ссылок (refcount)" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:491 msgid "" "Refcounts are interfaces for handling reference counters. They are " "implemented through atomic operations and are intended to be used just for " "cases, where the reference counter is the only one thing to be protected, so " "even something like a spin-mutex is deprecated. Using the refcount " "interface for structures, where a mutex is already used is often wrong since " "we should probably close the reference counter in some already protected " "paths. A manpage discussing refcount does not exist currently, just check [." "filename]#sys/refcount.h# for an overview of the existing API." msgstr "" "Счетчики ссылок (refcounts) — это интерфейсы для работы с подсчетом ссылок. " "Они реализованы с использованием атомарных операций и предназначены для " "случаев, когда счетчик ссылок — это единственное, что требует защиты, " "поэтому даже такие механизмы, как спин-мьютекс, не рекомендуются. " "Использование интерфейса refcount для структур, где уже применяется мьютекс, " "часто является ошибкой, так как, вероятно, следует защитить счетчик ссылок в " "рамках уже существующих защищенных участков кода. В настоящее время man-" "страница, посвященная refcount, отсутствует; для обзора существующего API " "обратитесь к [.filename]#sys/refcount.h#." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:493 #, no-wrap msgid "Locks" msgstr "Блокировки" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:498 msgid "" "FreeBSD kernel has huge classes of locks. Every lock is defined by some " "peculiar properties, but probably the most important is the event linked to " "contesting holders (or in other terms, the behavior of threads unable to " "acquire the lock). FreeBSD's locking scheme presents three different " "behaviors for contenders:" msgstr "" "Ядро FreeBSD имеет множество классов блокировок. Каждая блокировка " "определяется некоторыми уникальными свойствами, но, вероятно, наиболее " "важным является событие, связанное с конкурирующими владельцами (или, " "другими словами, поведение потоков, неспособных захватить блокировку). Схема " "блокировок FreeBSD предлагает три различных поведения для конкурирующих " "потоков:" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:500 msgid "spinning" msgstr "вращающиеся" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:501 msgid "blocking" msgstr "блокирующие" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:502 msgid "sleeping" msgstr "спящие" #. type: delimited block = 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:506 msgid "numbers are not casual" msgstr "номера приведены не случайно" #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:509 #, no-wrap msgid "Spinning locks" msgstr "Вращающиеся блокировки" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:515 msgid "" "Spin locks let waiters to spin until they cannot acquire the lock. An " "important matter do deal with is when a thread contests on a spin lock if it " "is not descheduled. Since the FreeBSD kernel is preemptive, this exposes " "spin lock at the risk of deadlocks that can be solved just disabling " "interrupts while they are acquired. For this and other reasons (like lack " "of priority propagation support, poorness in load balancing schemes between " "CPUs, etc.), spin locks are intended to protect very small paths of code, or " "ideally not to be used at all if not explicitly requested (explained later)." msgstr "" "Спин-блокировки позволяют ожидающим потокам продолжать работу (вращаться), " "пока они не смогут захватить блокировку. Важным аспектом является ситуация, " "когда поток соревнуется за спин-блокировку и не вытесняется. Поскольку ядро " "FreeBSD является вытесняющим, это подвергает спин-блокировки риску " "взаимоблокировок, которые можно устранить только отключением прерываний на " "время их удержания. По этой и другим причинам (таким как отсутствие " "поддержки распространения приоритетов, неэффективность схем балансировки " "нагрузки между CPU и т.д.), спин-блокировки предназначены для защиты очень " "небольших участков кода или, в идеале, не должны использоваться вовсе, если " "это не требуется явно (об этом далее)." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:517 #, no-wrap msgid "Blocking" msgstr "Блокирующие" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:522 msgid "" "Block locks let waiters to be descheduled and blocked until the lock owner " "does not drop it and wakes up one or more contenders. To avoid starvation " "issues, blocking locks do priority propagation from the waiters to the " "owner. Block locks must be implemented through the turnstile interface and " "are intended to be the most used kind of locks in the kernel, if no " "particular conditions are met." msgstr "" "Блокирующие блокировки позволяют ожидающим потокам быть выгруженными и " "заблокированными до тех пор, пока владелец блокировки не освободит её и не " "разбудит один или несколько конкурентов. Чтобы избежать проблем с " "голоданием, блокирующие блокировки передают приоритет от ожидающих к " "владельцу. Блокирующие блокировки должны быть реализованы через интерфейс " "турникета и предназначены для наиболее частого использования в ядре, если " "нет особых условий." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:524 #, no-wrap msgid "Sleeping" msgstr "Спящие" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:529 msgid "" "Sleep locks let waiters to be descheduled and fall asleep until the lock " "holder does not drop it and wakes up one or more waiters. Since sleep locks " "are intended to protect large paths of code and to cater asynchronous " "events, they do not do any form of priority propagation. They must be " "implemented through the man:sleepqueue[9] interface." msgstr "" "Спящие блокировки (с ожиданием) позволяют ожидающим потокам быть " "вытесненными и заснуть до тех пор, пока держатель блокировки не освободит её " "и не разбудит один или несколько ожидающих. Поскольку блокировки с ожиданием " "предназначены для защиты больших участков кода и обработки асинхронных " "событий, они не поддерживают распространение приоритетов. Они должны быть " "реализованы через интерфейс man:sleepqueue[9]." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:533 msgid "" "The order used to acquire locks is very important, not only for the " "possibility to deadlock due at lock order reversals, but even because lock " "acquisition should follow specific rules linked to locks natures. If you " "give a look at the table above, the practical rule is that if a thread holds " "a lock of level n (where the level is the number listed close to the kind of " "lock) it is not allowed to acquire a lock of superior levels, since this " "would break the specified semantic for a path. For example, if a thread " "holds a block lock (level 2), it is allowed to acquire a spin lock (level 1) " "but not a sleep lock (level 3), since block locks are intended to protect " "smaller paths than sleep lock (these rules are not about atomic operations " "or scheduling barriers, however)." msgstr "" "Порядок захвата блокировок очень важен, не только из-за возможности " "взаимоблокировки при обратном порядке захвата, но и потому, что захват " "блокировок должен следовать определённым правилам, связанным с их природой. " "Если взглянуть на таблицу выше, практическое правило заключается в том, что " "если поток удерживает блокировку уровня n (где уровень — это число, " "указанное рядом с типом блокировки), ему запрещено захватывать блокировки " "более высоких уровней, так как это нарушит заданную семантику пути. " "Например, если поток удерживает блокирующую блокировку (уровень 2), ему " "разрешено захватывать спин-блокировку (уровень 1), но не спящую блокировку " "(уровень 3), поскольку блокирующие блокировки предназначены для защиты более " "коротких путей, чем спящие блокировки (однако эти правила не касаются " "атомарных операций или барьеров планирования)." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:535 msgid "This is a list of lock with their respective behaviors:" msgstr "Вот список блокировок с соответствующими типами поведения:" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:537 msgid "spin mutex - spinning - man:mutex[9]" msgstr "spin mutex – вращающийся режим – man:mutex[9]" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:538 msgid "sleep mutex - blocking - man:mutex[9]" msgstr "sleep mutex – блокирующий режим – man:mutex[9]" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:539 msgid "pool mutex - blocking - man:mtx[pool]" msgstr "pool mutex – блокирующий режим – man:mtx[pool]" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:540 msgid "" "sleep family - sleeping - man:sleep[9] pause tsleep msleep msleep spin " "msleep rw msleep sx" msgstr "" "Семейство функций sleep – спящий режим – man:sleep[9] pause tsleep msleep " "msleep_spin msleep_rw msleep_sx" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:541 msgid "condvar - sleeping - man:condvar[9]" msgstr "condvar – спящий режим – man:condvar[9]" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:542 msgid "rwlock - blocking - man:rwlock[9]" msgstr "rwlock – блокирующий режим – man:rwlock[9]" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:543 msgid "sxlock - sleeping - man:sx[9]" msgstr "sxlock – спящий режим – man:sx[9]" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:544 msgid "lockmgr - sleeping - man:lockmgr[9]" msgstr "lockmgr – спящий режим – man:lockmgr[9]" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:545 msgid "semaphores - sleeping - man:sema[9]" msgstr "семафоры – спящий режим – man:sema[9]" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:547 msgid "" "Among these locks only mutexes, sxlocks, rwlocks and lockmgrs are intended " "to handle recursion, but currently recursion is only supported by mutexes " "and lockmgrs." msgstr "" "Среди этих блокировок только мьютексы, sxlock, rwlock и lockmgr " "предназначены для обработки рекурсии, но в настоящее время рекурсия " "поддерживается только мьютексами и lockmgr." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:549 #, no-wrap msgid "Scheduling barriers" msgstr "Барьеры планирования" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:553 msgid "" "Scheduling barriers are intended to be used to drive scheduling of " "threading. They consist mainly of three different stubs:" msgstr "" "Барьеры планирования предназначены для управления планированием потоков. Они " "в основном состоят из трёх различных заглушек:" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:555 msgid "critical sections (and preemption)" msgstr "критические секции (и вытеснение)" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:556 msgid "sched_bind" msgstr "sched_bind" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:557 msgid "sched_pin" msgstr "sched_pin" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:559 msgid "" "Generally, these should be used only in a particular context and even if " "they can often replace locks, they should be avoided because they do not let " "the diagnose of simple eventual problems with locking debugging tools (as " "man:witness[4])." msgstr "" "Как правило, их следует использовать только в определённом контексте, и даже " "если они часто могут заменять блокировки, их следует избегать, поскольку они " "не позволяют диагностировать простые потенциальные проблемы с помощью " "инструментов отладки блокировок (например, man:witness[4])." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:561 #, no-wrap msgid "Critical sections" msgstr "Критические секции" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:569 msgid "" "The FreeBSD kernel has been made preemptive basically to deal with interrupt " "threads. In fact, to avoid high interrupt latency, time-sharing priority " "threads can be preempted by interrupt threads (in this way, they do not need " "to wait to be scheduled as the normal path previews). Preemption, however, " "introduces new racing points that need to be handled, as well. Often, to " "deal with preemption, the simplest thing to do is to completely disable it. " "A critical section defines a piece of code (borderlined by the pair of " "functions man:critical_enter[9] and man:critical_exit[9], where preemption " "is guaranteed to not happen (until the protected code is fully executed). " "This can often replace a lock effectively but should be used carefully to " "not lose the whole advantage that preemption brings." msgstr "" "В ядре FreeBSD была реализована вытесняющая многозадачность в основном для " "работы с потоками обработки прерываний. Фактически, чтобы избежать высокой " "задержки прерываний, потоки с приоритетом разделения времени могут быть " "вытеснены потоками обработки прерываний (таким образом, им не нужно ждать " "планирования, как это предусмотрено в обычном случае). Однако вытеснение " "также вводит новые точки гонки, которые необходимо обрабатывать. Часто для " "борьбы с вытеснением проще всего полностью отключить его. Критическая секция " "определяет участок кода (ограниченный парой функций man:critical_enter[9] и " "man:critical_exit[9]), где гарантируется отсутствие вытеснения (пока " "защищённый код не будет полностью выполнен). Это часто может эффективно " "заменить блокировку, но должно использоваться осторожно, чтобы не потерять " "все преимущества, которые даёт вытеснение." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:571 #, no-wrap msgid "sched_pin/sched_unpin" msgstr "sched_pin/sched_unpin" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:577 msgid "" "Another way to deal with preemption is the `sched_pin()` interface. If a " "piece of code is closed in the `sched_pin()` and `sched_unpin()` pair of " "functions it is guaranteed that the respective thread, even if it can be " "preempted, it will always be executed on the same CPU. Pinning is very " "effective in the particular case when we have to access at per-cpu datas and " "we assume other threads will not change those data. The latter condition " "will determine a critical section as a too strong condition for our code." msgstr "" "Еще один способ работы с вытеснением — это интерфейс `sched_pin()`. Если " "участок кода заключен между функциями `sched_pin()` и `sched_unpin()`, " "гарантируется, что соответствующий поток, даже если он может быть вытеснен, " "всегда будет выполняться на том же CPU. Закрепление очень эффективно в " "частном случае, когда нам необходимо обращаться к данным, привязанным к " "определённым CPU, и мы предполагаем, что другие потоки не изменят эти " "данные. Последнее условие делает критическую секцию избыточно строгим " "условием для нашего кода." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:579 #, no-wrap msgid "sched_bind/sched_unbind" msgstr "sched_bind/sched_unbind" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:584 msgid "" "`sched_bind` is an API used to bind a thread to a particular CPU for all the " "time it executes the code, until a `sched_unbind` function call does not " "unbind it. This feature has a key role in situations where you cannot trust " "the current state of CPUs (for example, at very early stages of boot), as " "you want to avoid your thread to migrate on inactive CPUs. Since " "`sched_bind` and `sched_unbind` manipulate internal scheduler structures, " "they need to be enclosed in `sched_lock` acquisition/releasing when used." msgstr "" "`sched_bind` — это API, используемый для привязки потока к определённому CPU " "на всё время выполнения кода, пока вызов функции `sched_unbind` не отменит " "эту привязку. Эта функция играет ключевую роль в ситуациях, когда нельзя " "доверять текущему состоянию CPU (например, на самых ранних этапах загрузки), " "так как требуется избежать миграции потока на неактивные CPU. Поскольку " "`sched_bind` и `sched_unbind` работают с внутренними структурами " "планировщика, их использование должно быть заключено в захват/освобождение " "`sched_lock`." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:586 #, no-wrap msgid "Proc structure" msgstr "Структура proc" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:592 msgid "" "Various emulation layers sometimes require some additional per-process " "data. It can manage separate structures (a list, a tree etc.) containing " "these data for every process but this tends to be slow and memory " "consuming. To solve this problem the FreeBSD `proc` structure contains " "`p_emuldata`, which is a void pointer to some emulation layer specific " "data. This `proc` entry is protected by the proc mutex." msgstr "" "Различные уровни эмуляции иногда требуют дополнительных данных для каждого " "процесса. Можно управлять отдельными структурами (списком, деревом и т.д.), " "содержащими эти данные для каждого процесса, но это может быть медленно и " "потреблять много памяти. Чтобы решить эту проблему, структура `proc` в " "FreeBSD содержит `p_emuldata` — указатель типа void на данные, специфичные " "для уровня эмуляции. Эта запись `proc` защищена мьютексом proc." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:597 msgid "" "The FreeBSD `proc` structure contains a `p_sysent` entry that identifies, " "which ABI this process is running. In fact, it is a pointer to the " "`sysentvec` described above. So by comparing this pointer to the address " "where the `sysentvec` structure for the given ABI is stored we can " "effectively determine whether the process belongs to our emulation layer. " "The code typically looks like:" msgstr "" "Структура `proc` в FreeBSD содержит элемент `p_sysent`, который " "идентифицирует, под какой ABI работает данный процесс. Фактически, это " "указатель на упомянутый выше `sysentvec`. Таким образом, сравнивая этот " "указатель с адресом, по которому хранится структура `sysentvec` для данной " "ABI, мы можем эффективно определить, принадлежит ли процесс нашему " "эмуляционному слою. Код обычно выглядит следующим образом:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:602 #, no-wrap msgid "" "if (__predict_true(p->p_sysent != &elf_Linux(R)_sysvec))\n" "\t return;\n" msgstr "" "if (__predict_true(p->p_sysent != &elf_Linux(R)_sysvec))\n" "\t return;\n" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:606 msgid "" "As you can see, we effectively use the `__predict_true` modifier to collapse " "the most common case (FreeBSD process) to a simple return operation thus " "preserving high performance. This code should be turned into a macro " "because currently it is not very flexible, i.e. we do not support Linux(R)64 " "emulation nor A.OUT Linux(R) processes on i386." msgstr "" "Как видите, мы эффективно используем модификатор `__predict_true`, чтобы " "свести наиболее распространённый случай (процесс FreeBSD) к простой операции " "возврата, сохраняя высокую производительность. Этот код следует " "преобразовать в макрос, поскольку в настоящее время он не очень гибкий, " "например, мы не поддерживаем эмуляцию Linux(R)64, а также процессы Linux(R) " "в формате A.OUT на архитектуре i386." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:608 #, no-wrap msgid "VFS" msgstr "VFS" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:617 msgid "" "The FreeBSD VFS subsystem is very complex but the Linux(R) emulation layer " "uses just a small subset via a well defined API. It can either operate on " "vnodes or file handlers. Vnode represents a virtual vnode, i.e. " "representation of a node in VFS. Another representation is a file handler, " "which represents an opened file from the perspective of a process. A file " "handler can represent a socket or an ordinary file. A file handler contains " "a pointer to its vnode. More then one file handler can point to the same " "vnode." msgstr "" "Подсистема VFS в FreeBSD очень сложна, но слой эмуляции Linux(R) использует " "лишь небольшую её часть через чётко определённый API. Она может работать как " "с vnode, так и с файловыми дескрипторами. Vnode представляет собой " "виртуальный vnode, то есть представление узла в VFS. Другое представление — " "это файловый дескриптор, который представляет открытый файл с точки зрения " "процесса. Файловый дескриптор может представлять сокет или обычный файл. " "Файловый дескриптор содержит указатель на свой vnode. Более одного файлового " "дескриптора могут указывать на один и тот же vnode." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:619 #, no-wrap msgid "namei" msgstr "namei" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:626 msgid "" "The man:namei[9] routine is a central entry point to pathname lookup and " "translation. It traverses the path point by point from the starting point " "to the end point using lookup function, which is internal to VFS. The man:" "namei[9] syscall can cope with symlinks, absolute and relative paths. When " "a path is looked up using man:namei[9] it is inputed to the name cache. This " "behavior can be suppressed. This routine is used all over the kernel and " "its performance is very critical." msgstr "" "Функция man:namei[9] является центральной точкой входа для поиска и " "преобразования путей. Она проходит по пути шаг за шагом от начальной до " "конечной точки, используя функцию поиска, которая является внутренней для " "VFS. Системный вызов man:namei[9] может обрабатывать символьные ссылки, " "абсолютные и относительные пути. Когда путь ищется с помощью man:namei[9], " "он заносится в кэш имён. Это поведение можно отключить. Данная функция " "используется повсеместно в ядре, и её производительность крайне важна." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:628 #, no-wrap msgid "vn_fullpath" msgstr "vn_fullpath" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:634 msgid "" "The man:vn_fullpath[9] function takes the best effort to traverse VFS name " "cache and returns a path for a given (locked) vnode. This process is " "unreliable but works just fine for the most common cases. The unreliability " "is because it relies on VFS cache (it does not traverse the on medium " "structures), it does not work with hardlinks, etc. This routine is used in " "several places in the Linuxulator." msgstr "" "Функция man:vn_fullpath[9] предпринимает максимальные усилия для обхода кэша " "имён VFS и возвращает путь для заданного (заблокированного) vnode. Этот " "процесс ненадёжен, но в большинстве типичных случаев работает корректно. " "Ненадёжность обусловлена тем, что функция опирается на кэш VFS (она не " "обходит структуры на носителе), не работает с жёсткими ссылками и т.д. " "Данная процедура используется в нескольких местах Linuxulator." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:636 #, no-wrap msgid "Vnode operations" msgstr "Операции с vnode" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:639 msgid "" "`fgetvp` - given a thread and a file descriptor number it returns the " "associated vnode" msgstr "" "`fgetvp` - по заданным потоку и номеру файлового дескриптора возвращает " "связанный vnode" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:640 msgid "man:vn_lock[9] - locks a vnode" msgstr "man:vn_lock[9] - блокирует vnode" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:641 msgid "`vn_unlock` - unlocks a vnode" msgstr "`vn_unlock` - разблокирует vnode" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:642 msgid "man:VOP_READDIR[9] - reads a directory referenced by a vnode" msgstr "man:VOP_READDIR[9] - читает каталог, на который ссылается vnode" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:643 msgid "" "man:VOP_GETATTR[9] - gets attributes of a file or a directory referenced by " "a vnode" msgstr "" "man:VOP_GETATTR[9] - получает атрибуты файла или каталога, на который " "ссылается vnode" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:644 msgid "man:VOP_LOOKUP[9] - looks up a path to a given directory" msgstr "man:VOP_LOOKUP[9] - выполняет поиск пути к заданному каталогу" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:645 msgid "man:VOP_OPEN[9] - opens a file referenced by a vnode" msgstr "man:VOP_OPEN[9] - открывает файл, на который ссылается vnode" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:646 msgid "man:VOP_CLOSE[9] - closes a file referenced by a vnode" msgstr "man:VOP_CLOSE[9] - закрывает файл, на который ссылается vnode" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:647 msgid "man:vput[9] - decrements the use count for a vnode and unlocks it" msgstr "" "man:vput[9] - уменьшает счетчик использования для vnode и разблокирует его" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:648 msgid "man:vrele[9] - decrements the use count for a vnode" msgstr "man:vrele[9] - уменьшает счетчик использования для vnode" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:649 msgid "man:vref[9] - increments the use count for a vnode" msgstr "man:vref[9] - увеличивает счетчик использования для vnode" #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:651 #, no-wrap msgid "File handler operations" msgstr "Операции обработчика файлов (handler)" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:654 msgid "" "`fget` - given a thread and a file descriptor number it returns associated " "file handler and references it" msgstr "" "`fget` - для заданного потока и номера файлового дескриптора возвращает " "связанный обработчик файла и делает на него ссылку" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:655 msgid "`fdrop` - drops a reference to a file handler" msgstr "`fdrop` - освобождает ссылку на обработчик файлов" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:656 msgid "`fhold` - references a file handler" msgstr "`fhold` - ссылается на обработчик файла" #. type: Title == #: documentation/content/en/articles/linux-emulation/_index.adoc:658 #, no-wrap msgid "Linux(R) emulation layer -MD part" msgstr "Слой эмуляции Linux(R) - машинозависимая часть" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:666 msgid "" "This section deals with implementation of Linux(R) emulation layer in " "FreeBSD operating system. It first describes the machine dependent part " "talking about how and where interaction between userland and kernel is " "implemented. It talks about syscalls, signals, ptrace, traps, stack fixup. " "This part discusses i386 but it is written generally so other architectures " "should not differ very much. The next part is the machine independent part " "of the Linuxulator. This section only covers i386 and ELF handling. A.OUT " "is obsolete and untested." msgstr "" "В этом разделе рассматривается реализация слоя эмуляции Linux(R) в " "операционной системе FreeBSD. Сначала описывается машинозависимая часть, " "рассказывающая о том, как и где реализовано взаимодействие между " "пользовательским пространством и ядром. Рассматриваются системные вызовы, " "сигналы, ptrace, ловушки и исправление стека. Эта часть посвящена " "архитектуре i386, но написана в общем виде, поэтому другие архитектуры не " "должны сильно отличаться. Следующая часть — машинонезависимая часть " "Linuxulator. Этот раздел охватывает только i386 и обработку ELF. A.OUT " "устарел и не поддерживается." #. type: Title === #: documentation/content/en/articles/linux-emulation/_index.adoc:668 #, no-wrap msgid "Syscall handling" msgstr "Обработка системных вызовов" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:672 msgid "" "Syscall handling is mostly written in [.filename]#linux_sysvec.c#, which " "covers most of the routines pointed out in the `sysentvec` structure. When " "a Linux(R) process running on FreeBSD issues a syscall, the general syscall " "routine calls linux prepsyscall routine for the Linux(R) ABI." msgstr "" "Обработка системных вызовов в основном реализована в файле [." "filename]#linux_sysvec.c#, который покрывает большинство процедур, указанных " "в структуре `sysentvec`. Когда процесс Linux(R), выполняющийся на FreeBSD, " "делает системный вызов, общая процедура обработки системных вызовов вызывает " "linux prepsyscall для ABI Linux(R)." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:674 #, no-wrap msgid "Linux(R) prepsyscall" msgstr "Linux(R) prepsyscall" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:681 msgid "" "Linux(R) passes arguments to syscalls via registers (that is why it is " "limited to 6 parameters on i386) while FreeBSD uses the stack. The Linux(R) " "prepsyscall routine must copy parameters from registers to the stack. The " "order of the registers is: `%ebx`, `%ecx`, `%edx`, `%esi`, `%edi`, `%ebp`. " "The catch is that this is true for only _most_ of the syscalls. Some (most " "notably `clone`) uses a different order but it is luckily easy to fix by " "inserting a dummy parameter in the `linux_clone` prototype." msgstr "" "Linux(R) передаёт аргументы системных вызовов через регистры (поэтому на " "i386 ограничено 6 параметрами), тогда как FreeBSD использует стек. " "Подпрограмма Linux(R) `prepsyscall` должна копировать параметры из регистров " "в стек. Порядок регистров следующий: `%ebx`, `%ecx`, `%edx`, `%esi`, `%edi`" ", `%ebp`. Однако это верно только для _большинства_ системных вызовов. " "Некоторые (особенно `clone`) используют другой порядок, но это, к счастью, " "легко исправить, добавив фиктивный параметр в прототип `linux_clone`." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:683 #, no-wrap msgid "Syscall writing" msgstr "Как писать системные вызовы" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:687 msgid "" "Every syscall implemented in the Linuxulator must have its prototype with " "various flags in [.filename]#syscalls.master#. The form of the file is:" msgstr "" "Каждый системный вызов, реализованный в Linuxulator, должен иметь свой " "прототип с различными флагами в [.filename]#syscalls.master#. Формат файла " "следующий:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:695 #, no-wrap msgid "" "...\n" "\tAUE_FORK STD\t\t{ int linux_fork(void); }\n" "...\n" "\tAUE_CLOSE NOPROTO\t{ int close(int fd); }\n" "...\n" msgstr "" "...\n" "\tAUE_FORK STD\t\t{ int linux_fork(void); }\n" "...\n" "\tAUE_CLOSE NOPROTO\t{ int close(int fd); }\n" "...\n" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:705 msgid "" "The first column represents the syscall number. The second column is for " "auditing support. The third column represents the syscall type. It is " "either `STD`, `OBSOL`, `NOPROTO` and `UNIMPL`. `STD` is a standard syscall " "with full prototype and implementation. `OBSOL` is obsolete and defines " "just the prototype. `NOPROTO` means that the syscall is implemented " "elsewhere so do not prepend ABI prefix, etc. `UNIMPL` means that the " "syscall will be substituted with the `nosys` syscall (a syscall just " "printing out a message about the syscall not being implemented and returning " "`ENOSYS`)." msgstr "" "Первый столбец представляет номер системного вызова. Второй столбец " "предназначен для поддержки аудита. Третий столбец обозначает тип системного " "вызова. Он может быть `STD`, `OBSOL`, `NOPROTO` или `UNIMPL`. `STD` — это " "стандартный системный вызов с полным прототипом и реализацией. `OBSOL` " "означает устаревший вызов и определяет только прототип. `NOPROTO` означает, " "что системный вызов реализован в другом месте, поэтому не требует добавления " "префикса ABI и т.д. `UNIMPL` означает, что системный вызов будет заменён на " "`nosys` (системный вызов, который просто выводит сообщение о том, что вызов " "не реализован, и возвращает `ENOSYS`)." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:708 msgid "" "From [.filename]#syscalls.master# a script generates three files: [." "filename]#linux_syscall.h#, [.filename]#linux_proto.h# and [." "filename]#linux_sysent.c#. The [.filename]#linux_syscall.h# contains " "definitions of syscall names and their numerical value, e.g.:" msgstr "" "Из файла [.filename]#syscalls.master# скрипт генерирует три файла: [." "filename]#linux_syscall.h#, [.filename]#linux_proto.h# и [." "filename]#linux_sysent.c#. Файл [.filename]#linux_syscall.h# содержит " "определения имён системных вызовов и их числовых значений, например:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:716 #, no-wrap msgid "" "...\n" "#define LINUX_SYS_linux_fork 2\n" "...\n" "#define LINUX_SYS_close 6\n" "...\n" msgstr "" "...\n" "#define LINUX_SYS_linux_fork 2\n" "...\n" "#define LINUX_SYS_close 6\n" "...\n" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:719 msgid "" "The [.filename]#linux_proto.h# contains structure definitions of arguments " "to every syscall, e.g.:" msgstr "" "[.filename]#linux_proto.h# содержит определения структур аргументов для " "каждого системного вызова, например:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:725 #, no-wrap msgid "" "struct linux_fork_args {\n" " register_t dummy;\n" "};\n" msgstr "" "struct linux_fork_args {\n" " register_t dummy;\n" "};\n" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:728 msgid "" "And finally, [.filename]#linux_sysent.c# contains structure describing the " "system entry table, used to actually dispatch a syscall, e.g.:" msgstr "" "И, наконец, [.filename]#linux_sysent.c# содержит структуру, описывающую " "таблицу системных вызовов, используемую для фактической диспетчеризации " "системного вызова, например:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:733 #, no-wrap msgid "" "{ 0, (sy_call_t *)linux_fork, AUE_FORK, NULL, 0, 0 }, /* 2 = linux_fork */\n" "{ AS(close_args), (sy_call_t *)close, AUE_CLOSE, NULL, 0, 0 }, /* 6 = close */\n" msgstr "" "{ 0, (sy_call_t *)linux_fork, AUE_FORK, NULL, 0, 0 }, /* 2 = linux_fork */\n" "{ AS(close_args), (sy_call_t *)close, AUE_CLOSE, NULL, 0, 0 }, /* 6 = close */\n" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:737 msgid "" "As you can see `linux_fork` is implemented in Linuxulator itself so the " "definition is of `STD` type and has no argument, which is exhibited by the " "dummy argument structure. On the other hand `close` is just an alias for " "real FreeBSD man:close[2] so it has no linux arguments structure associated " "and in the system entry table it is not prefixed with linux as it calls the " "real man:close[2] in the kernel." msgstr "" "Как видно, `linux_fork` реализован в самом Linuxulator, поэтому определение " "имеет тип `STD` и не имеет аргументов, что демонстрируется структурой-" "заглушкой. С другой стороны, `close` — это просто псевдоним для настоящего " "FreeBSD man:close[2], поэтому у него нет связанной структуры аргументов " "Linux, и в системной таблице вызовов он не имеет префикса linux, так как " "вызывает настоящий man:close[2] в ядре." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:739 #, no-wrap msgid "Dummy syscalls" msgstr "Нереализованные системные вызовы" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:745 msgid "" "The Linux(R) emulation layer is not complete, as some syscalls are not " "implemented properly and some are not implemented at all. The emulation " "layer employs a facility to mark unimplemented syscalls with the `DUMMY` " "macro. These dummy definitions reside in [.filename]#linux_dummy.c# in a " "form of `DUMMY(syscall);`, which is then translated to various syscall " "auxiliary files and the implementation consists of printing a message saying " "that this syscall is not implemented. The `UNIMPL` prototype is not used " "because we want to be able to identify the name of the syscall that was " "called to know what syscalls are more important to implement." msgstr "" "Слой эмуляции Linux(R) не является полным, так как некоторые системные " "вызовы реализованы неправильно, а некоторые не реализованы вовсе. В слое " "эмуляции используется механизм для пометки нереализованных системных вызовов " "с помощью макроса `DUMMY`. Эти заглушки находятся в файле [." "filename]#linux_dummy.c# в форме `DUMMY(syscall);`, которые затем " "преобразуются в различные вспомогательные файлы системных вызовов, а их " "реализация сводится к выводу сообщения о том, что данный системный вызов не " "реализован. Прототип `UNIMPL` не используется, потому что мы хотим иметь " "возможность идентифицировать имя вызванного системного вызова, чтобы " "понимать, какие системные вызовы более важны для реализации." #. type: Title === #: documentation/content/en/articles/linux-emulation/_index.adoc:747 #, no-wrap msgid "Signal handling" msgstr "Обработка сигналов" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:751 msgid "" "Signal handling is done generally in the FreeBSD kernel for all binary " "compatibilities with a call to a compat-dependent layer. Linux(R) " "compatibility layer defines `linux_sendsig` routine for this purpose." msgstr "" "Обработка сигналов обычно выполняется в ядре FreeBSD для всех вариантов " "бинарной совместимости с помощью вызова уровня, зависящего от совместимости. " "Слой совместимости Linux(R) определяет для этой цели процедуру " "`linux_sendsig`." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:753 #, no-wrap msgid "Linux(R) sendsig" msgstr "Linux(R) sendsig" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:760 msgid "" "This routine first checks whether the signal has been installed with a " "`SA_SIGINFO` in which case it calls `linux_rt_sendsig` routine instead. " "Furthermore, it allocates (or reuses an already existing) signal handle " "context, then it builds a list of arguments for the signal handler. It " "translates the signal number based on the signal translation table, assigns " "a handler, translates sigset. Then it saves context for the `sigreturn` " "routine (various registers, translated trap number and signal mask). " "Finally, it copies out the signal context to the userspace and prepares " "context for the actual signal handler to run." msgstr "" "Эта процедура сначала проверяет, установлен ли сигнал с флагом `SA_SIGINFO`, " "в таком случае она вызывает процедуру `linux_rt_sendsig` вместо текущей. " "Далее она выделяет (или повторно использует уже существующий) контекст " "обработчика сигнала, затем формирует список аргументов для обработчика " "сигнала. Она преобразует номер сигнала на основе таблицы преобразования " "сигналов, назначает обработчик, преобразует sigset. Затем она сохраняет " "контекст для процедуры `sigreturn` (различные регистры, преобразованный " "номер trap и маску сигналов). Наконец, она копирует контекст сигнала в " "пользовательское пространство и подготавливает контекст для фактического " "выполнения обработчика сигнала." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:762 #, no-wrap msgid "linux_rt_sendsig" msgstr "linux_rt_sendsig" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:767 msgid "" "This routine is similar to `linux_sendsig` just the signal context " "preparation is different. It adds `siginfo`, `ucontext`, and some POSIX(R) " "parts. It might be worth considering whether those two functions could not " "be merged with a benefit of less code duplication and possibly even faster " "execution." msgstr "" "Эта процедура аналогична `linux_sendsig`, только подготовка контекста " "сигнала отличается. Она добавляет `siginfo`, `ucontext` и некоторые части " "POSIX(R). Стоит рассмотреть возможность объединения этих двух функций с " "выгодой в виде меньшего дублирования кода и, возможно, даже более быстрого " "выполнения." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:769 #, no-wrap msgid "linux_sigreturn" msgstr "linux_sigreturn" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:774 msgid "" "This syscall is used for return from the signal handler. It does some " "security checks and restores the original process context. It also unmasks " "the signal in process signal mask." msgstr "" "Этот системный вызов используется для возврата из обработчика сигнала. Он " "выполняет некоторые проверки безопасности и восстанавливает исходный " "контекст процесса. Также он разблокирует сигнал в маске сигналов процесса." #. type: Title === #: documentation/content/en/articles/linux-emulation/_index.adoc:776 #, no-wrap msgid "Ptrace" msgstr "Ptrace" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:782 msgid "" "Many UNIX(R) derivates implement the man:ptrace[2] syscall to allow various " "tracking and debugging features. This facility enables the tracing process " "to obtain various information about the traced process, like register dumps, " "any memory from the process address space, etc. and also to trace the " "process like in stepping an instruction or between system entries (syscalls " "and traps). man:ptrace[2] also lets you set various information in the " "traced process (registers etc.). man:ptrace[2] is a UNIX(R)-wide standard " "implemented in most UNIX(R)es around the world." msgstr "" "Многие производные UNIX(R) реализуют системный вызов man:ptrace[2] для " "обеспечения различных функций отслеживания и отладки. Этот механизм " "позволяет трассирующему процессу получать различную информацию о " "трассируемом процессе, такую как дампы регистров, любую память из адресного " "пространства процесса и т.д., а также трассировать процесс, например, " "пошагово выполнять инструкции или между системными вызовами (сисколлами и " "ловушками). man:ptrace[2] также позволяет устанавливать различную информацию " "в трассируемом процессе (регистры и т.д.). man:ptrace[2] является стандартом " "для UNIX(R), реализованным в большинстве UNIX(R)-систем по всему миру." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:788 msgid "" "Linux(R) emulation in FreeBSD implements the man:ptrace[2] facility in [." "filename]#linux_ptrace.c#. The routines for converting registers between " "Linux(R) and FreeBSD and the actual man:ptrace[2] syscall emulation " "syscall. The syscall is a long switch block that implements its counterpart " "in FreeBSD for every man:ptrace[2] command. The man:ptrace[2] commands are " "mostly equal between Linux(R) and FreeBSD so usually just a small " "modification is needed. For example, `PT_GETREGS` in Linux(R) operates on " "direct data while FreeBSD uses a pointer to the data so after performing a " "(native) man:ptrace[2] syscall, a copyout must be done to preserve Linux(R) " "semantics." msgstr "" "Эмуляция Linux(R) в FreeBSD реализует механизм man:ptrace[2] в файле [." "filename]#linux_ptrace.c#. Функции для преобразования регистров между " "Linux(R) и FreeBSD и фактический системный вызов эмуляции man:ptrace[2]. " "Системный вызов представляет собой длинный блок switch, который реализует " "свой аналог в FreeBSD для каждой команды man:ptrace[2]. Команды man:" "ptrace[2] в основном одинаковы между Linux(R) и FreeBSD, поэтому обычно " "требуется лишь небольшая модификация. Например, `PT_GETREGS` в Linux(R) " "работает с непосредственными данными, в то время как FreeBSD использует " "указатель на данные, поэтому после выполнения (нативного) системного вызова " "man:ptrace[2] необходимо выполнить copyout для сохранения семантики Linux(R)." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:792 msgid "" "The man:ptrace[2] implementation in Linuxulator has some known weaknesses. " "There have been panics seen when using `strace` (which is a man:ptrace[2] " "consumer) in the Linuxulator environment. Also `PT_SYSCALL` is not " "implemented." msgstr "" "Реализация man:ptrace[2] в Linuxulator имеет известные недостатки. " "Наблюдались паники при использовании `strace` (который является потребителем " "man:ptrace[2]) в среде Linuxulator. Также `PT_SYSCALL` не реализован." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:799 msgid "" "Whenever a Linux(R) process running in the emulation layer traps the trap " "itself is handled transparently with the only exception of the trap " "translation. Linux(R) and FreeBSD differs in opinion on what a trap is so " "this is dealt with here. The code is actually very short:" msgstr "" "Всякий раз, когда процесс Linux(R), выполняющийся в слое эмуляции, вызывает " "прерывание (trap), само прерывание обрабатывается прозрачно, за исключением " "преобразования прерывания. Linux(R) и FreeBSD расходятся во мнениях " "относительно того, что является прерыванием, поэтому этот вопрос решается " "здесь. Код на самом деле очень короткий:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:805 #, no-wrap msgid "" "static int\n" "translate_traps(int signal, int trap_code)\n" "{\n" msgstr "" "static int\n" "translate_traps(int signal, int trap_code)\n" "{\n" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:808 #, no-wrap msgid "" " if (signal != SIGBUS)\n" " return signal;\n" msgstr "" " if (signal != SIGBUS)\n" " return signal;\n" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:810 #, no-wrap msgid " switch (trap_code) {\n" msgstr " switch (trap_code) {\n" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:816 #, no-wrap msgid "" " case T_PROTFLT:\n" " case T_TSSFLT:\n" " case T_DOUBLEFLT:\n" " case T_PAGEFLT:\n" " return SIGSEGV;\n" msgstr "" " case T_PROTFLT:\n" " case T_TSSFLT:\n" " case T_DOUBLEFLT:\n" " case T_PAGEFLT:\n" " return SIGSEGV;\n" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:821 #, no-wrap msgid "" " default:\n" " return signal;\n" " }\n" "}\n" msgstr "" " default:\n" " return signal;\n" " }\n" "}\n" #. type: Title === #: documentation/content/en/articles/linux-emulation/_index.adoc:824 #, no-wrap msgid "Stack fixup" msgstr "Исправление стека" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:831 msgid "" "The RTLD run-time link-editor expects so called AUX tags on stack during an " "`execve` so a fixup must be done to ensure this. Of course, every RTLD " "system is different so the emulation layer must provide its own stack fixup " "routine to do this. So does Linuxulator. The `elf_linux_fixup` simply " "copies out AUX tags to the stack and adjusts the stack of the user space " "process to point right after those tags. So RTLD works in a smart way." msgstr "" "Динамический редактор связей RTLD ожидает так называемые AUX-теги на стеке " "во время выполнения `execve`, поэтому необходимо выполнить исправление, " "чтобы это обеспечить. Конечно, каждая система RTLD отличается, поэтому " "уровень эмуляции должен предоставлять собственную процедуру исправления " "стека. Linuxulator делает именно это. Функция `elf_linux_fixup` просто " "копирует AUX-теги на стек и корректирует стек пользовательского процесса, " "чтобы он указывал сразу после этих тегов. Таким образом, RTLD работает умным " "способом." #. type: Title === #: documentation/content/en/articles/linux-emulation/_index.adoc:833 #, no-wrap msgid "A.OUT support" msgstr "Поддержка A.OUT" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:840 msgid "" "The Linux(R) emulation layer on i386 also supports Linux(R) A.OUT binaries. " "Pretty much everything described in the previous sections must be " "implemented for A.OUT support (beside traps translation and signals " "sending). The support for A.OUT binaries is no longer maintained, " "especially the 2.6 emulation does not work with it but this does not cause " "any problem, as the linux-base in ports probably do not support A.OUT " "binaries at all. This support will probably be removed in future. Most of " "the stuff necessary for loading Linux(R) A.OUT binaries is in [." "filename]#imgact_linux.c# file." msgstr "" "Эмуляционный слой Linux(R) на i386 также поддерживает бинарные файлы " "Linux(R) в формате A.OUT. Почти всё, что описано в предыдущих разделах, " "должно быть реализовано для поддержки A.OUT (кроме перевода ловушек и " "отправки сигналов). Поддержка бинарных файлов A.OUT больше не " "поддерживается, в частности, эмуляция 2.6 с ними не работает, но это не " "вызывает никаких проблем, так как linux-base в портах, вероятно, вообще не " "поддерживает бинарные файлы A.OUT. Эта поддержка, скорее всего, будет " "удалена в будущем. Большая часть кода, необходимого для загрузки бинарных " "файлов Linux(R) A.OUT, находится в файле [.filename]#imgact_linux.c#." #. type: Title == #: documentation/content/en/articles/linux-emulation/_index.adoc:842 #, no-wrap msgid "Linux(R) emulation layer -MI part" msgstr "Слой эмуляции Linux(R) - машинонезависимая часть" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:847 msgid "" "This section talks about machine independent part of the Linuxulator. It " "covers the emulation infrastructure needed for Linux(R) 2.6 emulation, the " "thread local storage (TLS) implementation (on i386) and futexes. Then we " "talk briefly about some syscalls." msgstr "" "В этом разделе рассматривается машинонезависимая часть Linuxulator. Он " "охватывает инфраструктуру эмуляции, необходимую для эмуляции Linux(R) 2.6, " "реализацию thread local storage (TLS) (на i386) и фьютексы. Затем мы кратко " "обсуждаем некоторые системные вызовы." #. type: Title === #: documentation/content/en/articles/linux-emulation/_index.adoc:849 #, no-wrap msgid "Description of NPTL" msgstr "Описание NPTL" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:857 msgid "" "One of the major areas of progress in development of Linux(R) 2.6 was " "threading. Prior to 2.6, the Linux(R) threading support was implemented in " "the linuxthreads library. The library was a partial implementation of " "POSIX(R) threading. The threading was implemented using separate processes " "for each thread using the `clone` syscall to let them share the address " "space (and other things). The main weaknesses of this approach was that " "every thread had a different PID, signal handling was broken (from the " "pthreads perspective), etc. Also the performance was not very good (use of " "`SIGUSR` signals for threads synchronization, kernel resource consumption, " "etc.) so to overcome these problems a new threading system was developed and " "named NPTL." msgstr "" "Одним из основных направлений прогресса в разработке Linux(R) 2.6 стала " "поддержка потоков. До версии 2.6 поддержка потоков в Linux(R) " "реализовывалась в библиотеке linuxthreads. Эта библиотека представляла собой " "частичную реализацию потоков POSIX(R). Потоки создавались как отдельные " "процессы с использованием системного вызова `clone`, что позволяло им " "разделять адресное пространство (и другие ресурсы). Основными недостатками " "такого подхода были разные PID для каждого потока, некорректная обработка " "сигналов (с точки зрения pthreads) и т.д. Кроме того, производительность " "оставляла желать лучшего (использование сигналов `SIGUSR` для синхронизации " "потоков, потребление ресурсов ядра и т.п.), поэтому для решения этих проблем " "была разработана новая система потоков под названием NPTL." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:863 msgid "" "The NPTL library focused on two things but a third thing came along so it is " "usually considered a part of NPTL. Those two things were embedding of " "threads into a process structure and futexes. The additional third thing " "was TLS, which is not directly required by NPTL but the whole NPTL userland " "library depends on it. Those improvements yielded in much improved " "performance and standards conformance. NPTL is a standard threading library " "in Linux(R) systems these days." msgstr "" "Библиотека NPTL была сосредоточена на двух вещах, но появилась третья, " "поэтому её обычно считают частью NPTL. Этими двумя вещами были встраивание " "потоков в структуру процесса и фьютекс. Дополнительной третьей вещью стал " "TLS, который не требуется напрямую NPTL, но вся пользовательская библиотека " "NPTL зависит от него. Эти улучшения привели к значительному росту " "производительности и соответствию стандартам. В настоящее время NPTL " "является стандартной библиотекой потоков в системах Linux(R)." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:867 msgid "" "The FreeBSD Linuxulator implementation approaches the NPTL in three main " "areas. The TLS, futexes and PID mangling, which is meant to simulate the " "Linux(R) threads. Further sections describe each of these areas." msgstr "" "Реализация Linuxulator в FreeBSD подходит к NPTL в трёх основных " "направлениях: TLS, фьютекс и изменение PID, что предназначено для эмуляции " "потоков Linux(R). В следующих разделах описывается каждое из этих " "направлений." #. type: Title === #: documentation/content/en/articles/linux-emulation/_index.adoc:869 #, no-wrap msgid "Linux(R) 2.6 emulation infrastructure" msgstr "Инфраструктура эмуляции Linux(R) 2.6" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:872 msgid "" "These sections deal with the way Linux(R) threads are managed and how we " "simulate that in FreeBSD." msgstr "" "Эти разделы посвящены тому, как управляются потоки Linux(R) и как мы " "моделируем это в FreeBSD." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:874 #, no-wrap msgid "Runtime determining of 2.6 emulation" msgstr "Определение эмуляции 2.6 во время выполнения" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:883 msgid "" "The Linux(R) emulation layer in FreeBSD supports runtime setting of the " "emulated version. This is done via man:sysctl[8], namely `compat.linux." "osrelease`. Setting this man:sysctl[8] affects runtime behavior of the " "emulation layer. When set to 2.6.x it sets the value of `linux_use_linux26` " "while setting to something else keeps it unset. This variable (plus per-" "prison variables of the very same kind) determines whether 2.6 " "infrastructure (mainly PID mangling) is used in the code or not. The " "version setting is done system-wide and this affects all Linux(R) " "processes. The man:sysctl[8] should not be changed when running any " "Linux(R) binary as it might harm things." msgstr "" "Слой эмуляции Linux(R) в FreeBSD поддерживает динамическую настройку " "эмулируемой версии. Это выполняется с помощью man:sysctl[8], а именно " "`compat.linux.osrelease`. Установка этого man:sysctl[8] влияет на поведение " "слоя эмуляции во время выполнения. При установке значения 2.6.x " "устанавливается переменная `linux_use_linux26`, а при установке другого " "значения она остаётся сброшенной. Эта переменная (а также аналогичные " "переменные для каждой клетки) определяет, используется ли в коде " "инфраструктура 2.6 (в основном, преобразование PID). Настройка версии " "применяется глобально для всей системы и влияет на все процессы Linux(R). Не " "следует изменять man:sysctl[8] во время выполнения любого бинарного файла " "Linux(R), так как это может привести к проблемам." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:885 #, no-wrap msgid "Linux(R) processes and thread identifiers" msgstr "Идентификаторы процессов и потоков Linux(R)" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:892 msgid "" "The semantics of Linux(R) threading are a little confusing and uses entirely " "different nomenclature to FreeBSD. A process in Linux(R) consists of a " "`struct task` embedding two identifier fields - PID and TGID. PID is _not_ " "a process ID but it is a thread ID. The TGID identifies a thread group in " "other words a process. For single-threaded process the PID equals the TGID." msgstr "" "Семантика потоков в Linux(R) немного запутанная и использует совершенно " "другую терминологию по сравнению с FreeBSD. Процесс в Linux(R) состоит из " "`struct task`, включающей два поля идентификаторов — PID и TGID. PID — это " "_не_ идентификатор процесса, а идентификатор потока. TGID идентифицирует " "группу потоков, другими словами, процесс. Для однопоточного процесса PID " "равен TGID." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:898 msgid "" "The thread in NPTL is just an ordinary process that happens to have TGID not " "equal to PID and have a group leader not equal to itself (and shared VM etc. " "of course). Everything else happens in the same way as to an ordinary " "process. There is no separation of a shared status to some external " "structure like in FreeBSD. This creates some duplication of information and " "possible data inconsistency. The Linux(R) kernel seems to use task -> group " "information in some places and task information elsewhere and it is really " "not very consistent and looks error-prone." msgstr "" "Поток в NPTL — это обычный процесс, у которого TGID не равен PID и есть " "групповой лидер, отличный от него самого (и, конечно, общая виртуальная " "память и т.д.). Все остальное происходит так же, как и с обычным процессом. " "Нет разделения общего состояния на внешнюю структуру, как в FreeBSD. Это " -"создает некоторое дублирование информации и возможную несогласованность " +"создаёт некоторое дублирование информации и возможную несогласованность " "данных. Ядро Linux(R), похоже, использует информацию о задаче -> группе в " "одних местах и информацию о задаче в других, что не очень последовательно и " "выглядит небезопасно с точки зрения возможных ошибок." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:901 msgid "" "Every NPTL thread is created by a call to the `clone` syscall with a " "specific set of flags (more in the next subsection). The NPTL implements " "strict 1:1 threading." msgstr "" -"Каждый поток NPTL создается вызовом системного вызова `clone` с определённым " +"Каждый поток NPTL создаётся вызовом системного вызова `clone` с определённым " "набором флагов (подробнее в следующем подразделе). NPTL реализует строгую " "модель потоков 1:1." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:903 msgid "" "In FreeBSD we emulate NPTL threads with ordinary FreeBSD processes that " "share VM space, etc. and the PID gymnastic is just mimicked in the emulation " "specific structure attached to the process. The structure attached to the " "process looks like:" msgstr "" "В FreeBSD мы эмулируем потоки NPTL с помощью обычных процессов FreeBSD, " "которые разделяют виртуальную память и т.д., а гимнастика с PID просто " "имитируется в специфической для эмуляции структуре, прикреплённой к " "процессу. Структура, прикреплённая к процессу, выглядит следующим образом:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:908 #, no-wrap msgid "" "struct linux_emuldata {\n" " pid_t pid;\n" msgstr "" "struct linux_emuldata {\n" " pid_t pid;\n" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:911 #, no-wrap msgid "" " int *child_set_tid; /* in clone(): Child.s TID to set on clone */\n" " int *child_clear_tid;/* in clone(): Child.s TID to clear on exit */\n" msgstr "" " int *child_set_tid; /* in clone(): Child.s TID to set on clone */\n" " int *child_clear_tid;/* in clone(): Child.s TID to clear on exit */\n" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:913 #, no-wrap msgid " struct linux_emuldata_shared *shared;\n" msgstr " struct linux_emuldata_shared *shared;\n" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:915 #, no-wrap msgid " int pdeath_signal; /* parent death signal */\n" msgstr " int pdeath_signal; /* parent death signal */\n" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:918 #, no-wrap msgid "" " LIST_ENTRY(linux_emuldata) threads; /* list of linux threads */\n" "};\n" msgstr "" " LIST_ENTRY(linux_emuldata) threads; /* list of linux threads */\n" "};\n" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:925 msgid "" "The PID is used to identify the FreeBSD process that attaches this " "structure. The `child_se_tid` and `child_clear_tid` are used for TID " "address copyout when a process exits and is created. The `shared` pointer " "points to a structure shared among threads. The `pdeath_signal` variable " "identifies the parent death signal and the `threads` pointer is used to link " "this structure to the list of threads. The `linux_emuldata_shared` " "structure looks like:" msgstr "" "PID используется для идентификации процесса FreeBSD, к которому присоединена " "эта структура. `child_se_tid` и `child_clear_tid` используются для " "копирования адреса TID при завершении и создании процесса. Указатель " "`shared` указывает на структуру, разделяемую между потоками. Переменная " "`pdeath_signal` определяет сигнал завершения родительского процесса, а " "указатель `threads` используется для связывания этой структуры со списком " "потоков. Структура `linux_emuldata_shared` выглядит следующим образом:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:929 #, no-wrap msgid "struct linux_emuldata_shared {\n" msgstr "struct linux_emuldata_shared {\n" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:931 #, no-wrap msgid " int refs;\n" msgstr " int refs;\n" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:933 #, no-wrap msgid " pid_t group_pid;\n" msgstr " pid_t group_pid;\n" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:936 #, no-wrap msgid "" " LIST_HEAD(, linux_emuldata) threads; /* head of list of linux threads */\n" "};\n" msgstr "" " LIST_HEAD(, linux_emuldata) threads; /* head of list of linux threads */\n" "};\n" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:941 msgid "" "The `refs` is a reference counter being used to determine when we can free " "the structure to avoid memory leaks. The `group_pid` is to identify PID ( = " "TGID) of the whole process ( = thread group). The `threads` pointer is the " "head of the list of threads in the process." msgstr "" "`refs` — это счётчик ссылок, используемый для определения момента, когда " "можно освободить структуру, чтобы избежать утечек памяти. `group_pid` служит " "для идентификации PID (= TGID) всего процесса (= группы потоков). Указатель " "`threads` является головой списка потоков в процессе." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:944 msgid "" "The `linux_emuldata` structure can be obtained from the process using " "`em_find`. The prototype of the function is:" msgstr "" "Структуру `linux_emuldata` можно получить из процесса с помощью `em_find`. " "Прототип функции выглядит следующим образом:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:948 #, no-wrap msgid "struct linux_emuldata *em_find(struct proc *, int locked);\n" msgstr "struct linux_emuldata *em_find(struct proc *, int locked);\n" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:953 msgid "" "Here, `proc` is the process we want the emuldata structure from and the " "locked parameter determines whether we want to lock or not. The accepted " "values are `EMUL_DOLOCK` and `EMUL_DOUNLOCK`. More about locking later." msgstr "" "Здесь `proc` — это процесс, из которого мы хотим получить структуру " "`emuldata`, а параметр `locked` определяет, нужно ли блокировать. Допустимые " "значения — `EMUL_DOLOCK` и `EMUL_DOUNLOCK`. Подробнее о блокировке позже." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:955 #, no-wrap msgid "PID mangling" msgstr "Преобразование PID" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:962 msgid "" "As there is a difference in view as what to the idea of a process ID and " "thread ID is between FreeBSD and Linux(R) we have to translate the view " "somehow. We do it by PID mangling. This means that we fake what a PID " "(=TGID) and TID (=PID) is between kernel and userland. The rule of thumb is " "that in kernel (in Linuxulator) PID = PID and TGID = shared -> group pid and " "to userland we present `PID = shared -> group_pid` and `TID = proc -> " "p_pid`. The PID member of `linux_emuldata structure` is a FreeBSD PID." msgstr "" "Поскольку между FreeBSD и Linux(R) существуют различия в представлении " "идентификатора процесса (PID) и идентификатора потока (TID), нам необходимо " "преобразовывать эти понятия. Это достигается за счёт модификации PID. Это " "означает, что мы изменяем представление о PID (=TGID) и TID (=PID) между " "ядром и пользовательским пространством. Основное правило заключается в " "следующем: в ядре (в Linuxulator) `PID = PID`, а `TGID = shared -> " "group_pid`; для пользовательского пространства мы представляем `PID = shared " "-> group_pid` и `TID = proc -> p_pid`. Член `PID` в структуре " "`linux_emuldata` является FreeBSD PID." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:966 msgid "" "The above affects mainly getpid, getppid, gettid syscalls. Where we use PID/" "TGID respectively. In copyout of TIDs in `child_clear_tid` and " "`child_set_tid` we copy out FreeBSD PID." msgstr "" "Вышесказанное в основном влияет на системные вызовы getpid, getppid, gettid. " "В случаях, где мы используем PID/TGID соответственно. При копировании TID в " "`child_clear_tid` и `child_set_tid` мы копируем FreeBSD PID." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:968 #, no-wrap msgid "Clone syscall" msgstr "Системный вызов clone" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:972 msgid "" "The `clone` syscall is the way threads are created in Linux(R). The syscall " "prototype looks like this:" msgstr "" "`clone` — это системный вызов, с помощью которого создаются потоки в " "Linux(R). Прототип системного вызова выглядит следующим образом:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:977 #, no-wrap msgid "" "int linux_clone(l_int flags, void *stack, void *parent_tidptr, int dummy,\n" "void * child_tidptr);\n" msgstr "" "int linux_clone(l_int flags, void *stack, void *parent_tidptr, int dummy,\n" "void * child_tidptr);\n" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:987 msgid "" "The `flags` parameter tells the syscall how exactly the processes should be " "cloned. As described above, Linux(R) can create processes sharing various " "things independently, for example two processes can share file descriptors " "but not VM, etc. Last byte of the `flags` parameter is the exit signal of " "the newly created process. The `stack` parameter if non-`NULL` tells, where " "the thread stack is and if it is `NULL` we are supposed to copy-on-write the " "calling process stack (i.e. do what normal man:fork[2] routine does). The " "`parent_tidptr` parameter is used as an address for copying out process PID " "(i.e. thread id) once the process is sufficiently instantiated but is not " "runnable yet. The `dummy` parameter is here because of the very strange " "calling convention of this syscall on i386. It uses the registers directly " "and does not let the compiler do it what results in the need of a dummy " "syscall. The `child_tidptr` parameter is used as an address for copying out " "PID once the process has finished forking and when the process exits." msgstr "" "Параметр `flags` указывает системному вызову, как именно процессы должны " "быть клонированы. Как описано выше, Linux(R) может создавать процессы, " "разделяющие различные ресурсы независимо, например, два процесса могут " "разделять файловые дескрипторы, но не виртуальную память и т.д. Последний " "байт параметра `flags` является сигналом завершения для вновь созданного " "процесса. Параметр `stack`, если он не `NULL`, указывает, где находится стек " "потока, а если он `NULL`, предполагается копирование при записи стека " "вызывающего процесса (т.е. делать то же, что делает обычная функция man:" "fork[2]). Параметр `parent_tidptr` используется как адрес для копирования " "PID процесса (т.е. идентификатора потока) после того, как процесс достаточно " "инициализирован, но ещё не готов к выполнению. Параметр `dummy` присутствует " "из-за очень странного соглашения о вызовах этого системного вызова на i386. " "Он использует регистры напрямую и не позволяет компилятору делать это, что " "приводит к необходимости использования фиктивного системного вызова. " "Параметр `child_tidptr` используется как адрес для копирования PID после " "завершения ветвления процесса и при его завершении." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1001 msgid "" "The syscall itself proceeds by setting corresponding flags depending on the " "flags passed in. For example, `CLONE_VM` maps to RFMEM (sharing of VM), " "etc. The only nit here is `CLONE_FS` and `CLONE_FILES` because FreeBSD does " "not allow setting this separately so we fake it by not setting RFFDG " "(copying of fd table and other fs information) if either of these is " "defined. This does not cause any problems, because those flags are always " "set together. After setting the flags the process is forked using the " "internal `fork1` routine, the process is instrumented not to be put on a run " "queue, i.e. not to be set runnable. After the forking is done we possibly " "reparent the newly created process to emulate `CLONE_PARENT` semantics. " "Next part is creating the emulation data. Threads in Linux(R) does not " "signal their parents so we set exit signal to be 0 to disable this. After " "that setting of `child_set_tid` and `child_clear_tid` is performed enabling " "the functionality later in the code. At this point we copy out the PID to " "the address specified by `parent_tidptr`. The setting of process stack is " "done by simply rewriting thread frame `%esp` register (`%rsp` on amd64). " "Next part is setting up TLS for the newly created process. After this man:" "vfork[2] semantics might be emulated and finally the newly created process " "is put on a run queue and copying out its PID to the parent process via " "`clone` return value is done." msgstr "" "Системный вызов продолжает выполнение, устанавливая соответствующие флаги в " "зависимости от переданных аргументов. Например, `CLONE_VM` преобразуется в " "RFMEM (общее адресное пространство) и т.д. Единственная тонкость здесь — это " "`CLONE_FS` и `CLONE_FILES`, поскольку FreeBSD не позволяет устанавливать их " "отдельно, поэтому мы эмулируем это, не устанавливая RFFDG (копирование " "таблицы файловых дескрипторов и другой информации о файловой системе), если " "задан любой из этих флагов. Это не вызывает проблем, так как эти флаги " "всегда устанавливаются вместе. После установки флагов процесс создаётся с " "помощью внутренней процедуры `fork1`, при этом процесс настраивается так, " "чтобы не помещаться в очередь выполнения (т.е. не становиться исполняемым). " "После завершения ветвления мы, при необходимости, изменяем родителя для " "нового процесса, чтобы эмулировать семантику `CLONE_PARENT`. Следующий шаг — " "создание данных эмуляции. Потоки в Linux(R) не отправляют сигналы своим " "родителям, поэтому мы устанавливаем сигнал завершения в 0, чтобы отключить " "эту возможность. Затем выполняется настройка `child_set_tid` и " "`child_clear_tid`, что активирует соответствующую функциональность далее в " "коде. На этом этапе мы копируем PID по адресу, указанному в `parent_tidptr`. " "Установка стека процесса выполняется простой перезаписью регистра `%esp` (`" "%rsp` на amd64) в кадре потока. Далее настраивается TLS для нового процесса. " "После этого может быть эмулирована семантика man:vfork[2], и, наконец, новый " "процесс помещается в очередь выполнения, а его PID возвращается " "родительскому процессу через возвращаемое значение `clone`." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1004 msgid "" "The `clone` syscall is able and in fact is used for emulating classic man:" "fork[2] and man:vfork[2] syscalls. Newer glibc in a case of 2.6 kernel uses " "`clone` to implement man:fork[2] and man:vfork[2] syscalls." msgstr "" "Системный вызов `clone` способен и фактически используется для эмуляции " "классических системных вызовов man:fork[2] и man:vfork[2]. Более новые " "версии glibc в случае ядра 2.6 используют `clone` для реализации системных " "вызовов man:fork[2] и man:vfork[2]." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:1006 #, no-wrap msgid "Locking" msgstr "Блокировка" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1012 msgid "" "The locking is implemented to be per-subsystem because we do not expect a " "lot of contention on these. There are two locks: `emul_lock` used to " "protect manipulating of `linux_emuldata` and `emul_shared_lock` used to " "manipulate `linux_emuldata_shared`. The `emul_lock` is a nonsleepable " "blocking mutex while `emul_shared_lock` is a sleepable blocking `sx_lock`. " "Due to of the per-subsystem locking we can coalesce some locks and that is " "why the em_find offers the non-locking access." msgstr "" "Блокировка реализована на уровне подсистем, поскольку не ожидается высокой " "конкуренции за эти ресурсы. Существует две блокировки: `emul_lock`, " "используемая для защиты манипуляций с `linux_emuldata`, и `emul_shared_lock`" ", используемая для манипуляций с `linux_emuldata_shared`. `emul_lock` " "представляет собой неспящий блокирующий мьютекс, в то время как " "`emul_shared_lock` — это спящий блокирующий `sx_lock`. Благодаря блокировке " "на уровне подсистем мы можем объединять некоторые блокировки, поэтому " "em_find предлагает доступ без блокировки." #. type: Title === #: documentation/content/en/articles/linux-emulation/_index.adoc:1014 #, no-wrap msgid "TLS" msgstr "TLS" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1017 msgid "This section deals with TLS also known as thread local storage." msgstr "" "Этот раздел посвящён TLS, также известному как локальное хранилище потока." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:1019 #, no-wrap msgid "Introduction to threading" msgstr "Введение в многопоточность" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1040 msgid "" "Threads in computer science are entities within a process that can be " "scheduled independently from each other. The threads in the process share " "process wide data (file descriptors, etc.) but also have their own stack for " "their own data. Sometimes there is a need for process-wide data specific to " "a given thread. Imagine a name of the thread in execution or something like " "that. The traditional UNIX(R) threading API, pthreads provides a way to do " "it via man:pthread_key_create[3], man:pthread_setspecific[3] and man:" "pthread_getspecific[3] where a thread can create a key to the thread local " "data and using man:pthread_getspecific[3] or man:pthread_getspecific[3] to " "manipulate those data. You can easily see that this is not the most " "comfortable way this could be accomplished. So various producers of C/C++ " "compilers introduced a better way. They defined a new modifier keyword " "thread that specifies that a variable is thread specific. A new method of " "accessing such variables was developed as well (at least on i386). The " "pthreads method tends to be implemented in userspace as a trivial lookup " "table. The performance of such a solution is not very good. So the new " "method uses (on i386) segment registers to address a segment, where TLS area " "is stored so the actual accessing of a thread variable is just appending the " "segment register to the address thus addressing via it. The segment " "registers are usually `%gs` and `%fs` acting like segment selectors. Every " "thread has its own area where the thread local data are stored and the " "segment must be loaded on every context switch. This method is very fast " "and used almost exclusively in the whole i386 UNIX(R) world. Both FreeBSD " "and Linux(R) implement this approach and it yields very good results. The " "only drawback is the need to reload the segment on every context switch " "which can slowdown context switches. FreeBSD tries to avoid this overhead " "by using only 1 segment descriptor for this while Linux(R) uses 3. " "Interesting thing is that almost nothing uses more than 1 descriptor (only " "Wine seems to use 2) so Linux(R) pays this unnecessary price for context " "switches." msgstr "" "В компьютерных науках потоки (threads) — это сущности внутри процесса, " "которые могут планироваться независимо друг от друга. Потоки в процессе " "разделяют общие данные процесса (например, файловые дескрипторы), но также " "имеют свой собственный стек для своих данных. Иногда возникает необходимость " "в данных, специфичных для конкретного потока, но доступных на уровне " "процесса. Например, имя выполняемого потока или что-то подобное. " "Традиционный API для работы с потоками в UNIX® — pthreads — предоставляет " "способ сделать это через функции `man:pthread_key_create[3]`, `man:" "pthread_setspecific[3]` и `man:pthread_getspecific[3]`, где поток может " "создать ключ к локальным данным потока и использовать `man:" "pthread_getspecific[3]` или `man:pthread_getspecific[3]` для управления " "этими данными. Легко заметить, что это не самый удобный способ. Поэтому " "различные разработчики компиляторов C/C++ предложили более удобный метод. " "Они ввели новое ключевое слово `thread`, которое указывает, что переменная " "является специфичной для потока. Также был разработан новый метод доступа к " "таким переменным (по крайней мере, на архитектуре i386). Метод pthreads " "обычно реализуется в пользовательском пространстве в виде простой таблицы " "поиска. Производительность такого решения не очень высока. Новый метод " "использует (на i386) сегментные регистры для адресации области, где хранится " "TLS (Thread-Local Storage), так что фактический доступ к переменной потока " "сводится к добавлению сегментного регистра к адресу, таким образом обращаясь " "через него. Сегментные регистры, обычно `%gs` и `%fs`, действуют как " "селекторы сегментов. Каждый поток имеет свою собственную область, где " "хранятся локальные данные потока, и сегмент должен загружаться при каждом " "переключении контекста. Этот метод очень быстрый и используется практически " "повсеместно в мире UNIX® на архитектуре i386. И FreeBSD, и Linux® реализуют " "этот подход, и он даёт очень хорошие результаты. Единственный недостаток — " "необходимость перезагружать сегмент при каждом переключении контекста, что " "может замедлять переключения. FreeBSD пытается минимизировать эти накладные " "расходы, используя только 1 дескриптор сегмента, в то время как Linux® " "использует 3. Интересно, что почти ничто не использует больше 1 дескриптора " "(только Wine, кажется, использует 2), поэтому Linux® платит эту " "необязательную цену при переключении контекстов." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:1042 #, no-wrap msgid "Segments on i386" msgstr "Сегменты на i386" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1049 msgid "" "The i386 architecture implements the so called segments. A segment is a " "description of an area of memory. The base address (bottom) of the memory " "area, the end of it (ceiling), type, protection, etc. The memory described " "by a segment can be accessed using segment selector registers (`%cs`, `%ds`, " "`%ss`, `%es`, `%fs`, `%gs`). For example let us suppose we have a segment " "which base address is 0x1234 and length and this code:" msgstr "" "Архитектура i386 реализует так называемые сегменты. Сегмент — это описание " "области памяти. Он включает базовый адрес (начало) области памяти, её конец " "(границу), тип, защиту и т.д. Доступ к памяти, описываемой сегментом, может " "осуществляться с использованием регистров селекторов сегментов (`%cs`, `" "%ds`, `%ss`, `%es`, `%fs`, `%gs`). Например, предположим, что у нас есть " "сегмент с базовым адресом 0x1234 и длиной, а также следующий код:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:1053 #, no-wrap msgid "mov %edx,%gs:0x10\n" msgstr "mov %edx,%gs:0x10\n" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1062 msgid "" "This will load the content of the `%edx` register into memory location " "0x1244. Some segment registers have a special use, for example `%cs` is " "used for code segment and `%ss` is used for stack segment but `%fs` and `" "%gs` are generally unused. Segments are either stored in a global GDT table " "or in a local LDT table. LDT is accessed via an entry in the GDT. The LDT " "can store more types of segments. LDT can be per process. Both tables " "define up to 8191 entries." msgstr "" "Это загрузит содержимое регистра `%edx` в ячейку памяти по адресу 0x1244. " "Некоторые сегментные регистры имеют специальное назначение, например, `%cs` " "используется для сегмента кода, а `%ss` — для сегмента стека, но `%fs` и `" "%gs` обычно не используются. Сегменты хранятся либо в глобальной таблице " "GDT, либо в локальной таблице LDT. Доступ к LDT осуществляется через запись " "в GDT. LDT может хранить больше типов сегментов. LDT может быть отдельной " "для каждого процесса. Обе таблицы определяют до 8191 записей." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:1064 #, no-wrap msgid "Implementation on Linux(R) i386" msgstr "Реализация на Linux(R) i386" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1072 msgid "" "There are two main ways of setting up TLS in Linux(R). It can be set when " "cloning a process using the `clone` syscall or it can call " "`set_thread_area`. When a process passes `CLONE_SETTLS` flag to `clone`, " "the kernel expects the memory pointed to by the `%esi` register a Linux(R) " "user space representation of a segment, which gets translated to the machine " "representation of a segment and loaded into a GDT slot. The GDT slot can be " "specified with a number or -1 can be used meaning that the system itself " "should choose the first free slot. In practice, the vast majority of " "programs use only one TLS entry and does not care about the number of the " "entry. We exploit this in the emulation and in fact depend on it." msgstr "" "Существует два основных способа настройки TLS в Linux(R). Он может быть " "настроен при клонировании процесса с использованием системного вызова `clone`" " или с помощью вызова `set_thread_area`. Когда процесс передаёт флаг " "`CLONE_SETTLS` в `clone`, ядро ожидает, что память, на которую указывает " "регистр `%esi`, будет содержать пользовательское представление сегмента в " "Linux(R), которое преобразуется в машинное представление сегмента и " "загружается в слот GDT. Слот GDT может быть указан номером или можно " "использовать -1, что означает, что система сама должна выбрать первый " "свободный слот. На практике подавляющее большинство программ используют " "только одну запись TLS и не заботятся о номере записи. Мы используем это в " "эмуляции и фактически зависим от этого." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:1074 #, no-wrap msgid "Emulation of Linux(R) TLS" msgstr "Эмуляция Linux(R) TLS" #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:1077 #, no-wrap msgid "i386" msgstr "i386" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1095 msgid "" "Loading of TLS for the current thread happens by calling `set_thread_area` " "while loading TLS for a second process in `clone` is done in the separate " "block in `clone`. Those two functions are very similar. The only " "difference being the actual loading of the GDT segment, which happens on the " "next context switch for the newly created process while `set_thread_area` " "must load this directly. The code basically does this. It copies the " "Linux(R) form segment descriptor from the userland. The code checks for the " "number of the descriptor but because this differs between FreeBSD and " "Linux(R) we fake it a little. We only support indexes of 6, 3 and -1. The " "6 is genuine Linux(R) number, 3 is genuine FreeBSD one and -1 means " "autoselection. Then we set the descriptor number to constant 3 and copy out " "this to the userspace. We rely on the userspace process using the number " "from the descriptor but this works most of the time (have never seen a case " "where this did not work) as the userspace process typically passes in 1. " "Then we convert the descriptor from the Linux(R) form to a machine dependant " "form (i.e. operating system independent form) and copy this to the FreeBSD " "defined segment descriptor. Finally we can load it. We assign the " "descriptor to threads PCB (process control block) and load the `%gs` segment " "using `load_gs`. This loading must be done in a critical section so that " "nothing can interrupt us. The `CLONE_SETTLS` case works exactly like this " "just the loading using `load_gs` is not performed. The segment used for " "this (segment number 3) is shared for this use between FreeBSD processes and " "Linux(R) processes so the Linux(R) emulation layer does not add any overhead " "over plain FreeBSD." msgstr "" "Загрузка TLS для текущего потока происходит путем вызова `set_thread_area`, " "тогда как загрузка TLS для второго процесса в `clone` выполняется в " "отдельном блоке в `clone`. Эти две функции очень похожи. Единственное " "различие заключается в фактической загрузке сегмента GDT, которая происходит " "при следующем переключении контекста для вновь созданного процесса, в то " "время как `set_thread_area` должен загрузить его напрямую. Код в основном " "делает следующее. Он копирует дескриптор сегмента в формате Linux(R) из " "пользовательского пространства. Код проверяет номер дескриптора, но " "поскольку он различается между FreeBSD и Linux(R), мы немного имитируем его. " "Мы поддерживаем только индексы 6, 3 и -1. Число 6 — это оригинальный номер " "Linux(R), 3 — оригинальный номер FreeBSD, а -1 означает авто-выбор. Затем мы " "устанавливаем номер дескриптора на константу 3 и копируем его обратно в " "пользовательское пространство. Мы полагаемся на то, что процесс в " "пользовательском пространстве использует номер из дескриптора, но это " "работает в большинстве случаев (никогда не встречалось ситуации, когда это " "не срабатывало), так как процесс в пользовательском пространстве обычно " "передаёт 1. Затем мы преобразуем дескриптор из формата Linux(R) в " "машинозависимую форму (т.е. независимую от операционной системы) и копируем " "его в дескриптор сегмента, определённый FreeBSD. Наконец, мы можем загрузить " "его. Мы назначаем дескриптор PCB потока (блок управления процессом) и " "загружаем сегмент `%gs` с помощью `load_gs`. Эта загрузка должна выполняться " "в критической секции, чтобы ничто не могло нас прервать. Случай " "`CLONE_SETTLS` работает точно так же, только загрузка с помощью `load_gs` не " "выполняется. Сегмент, используемый для этого (сегмент номер 3), разделяется " "между процессами FreeBSD и Linux(R), поэтому слой эмуляции Linux(R) не " "добавляет накладных расходов по сравнению с обычным FreeBSD." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:1097 #, no-wrap msgid "amd64" msgstr "amd64" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1101 msgid "" "The amd64 implementation is similar to the i386 one but there was initially " "no 32bit segment descriptor used for this purpose (hence not even native " "32bit TLS users worked) so we had to add such a segment and implement its " "loading on every context switch (when a flag signaling use of 32bit is " "set). Apart from this the TLS loading is exactly the same just the segment " "numbers are different and the descriptor format and the loading differs " "slightly." msgstr "" "Реализация amd64 аналогична реализации i386, но изначально не использовался " "32-битный дескриптор сегмента для этой цели (поэтому даже нативные " "пользователи 32-битного TLS не работали), поэтому нам пришлось добавить " "такой сегмент и реализовать его загрузку при каждом переключении контекста " "(когда установлен флаг, сигнализирующий о использовании 32-битного режима). " "Кроме этого, загрузка TLS точно такая же, только номера сегментов " "отличаются, а формат дескриптора и загрузка немного различаются." #. type: Title === #: documentation/content/en/articles/linux-emulation/_index.adoc:1103 #, no-wrap msgid "Futexes" msgstr "Фьютексы" #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:1106 #, no-wrap msgid "Introduction to synchronization" msgstr "Введение в синхронизацию" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1116 msgid "" "Threads need some kind of synchronization and POSIX(R) provides some of " "them: mutexes for mutual exclusion, read-write locks for mutual exclusion " "with biased ratio of reads and writes and condition variables for signaling " "a status change. It is interesting to note that POSIX(R) threading API " "lacks support for semaphores. Those synchronization routines " "implementations are heavily dependant on the type threading support we " "have. In pure 1:M (userspace) model the implementation can be solely done " "in userspace and thus be very fast (the condition variables will probably " "end up being implemented using signals, i.e. not fast) and simple. In 1:1 " "model, the situation is also quite clear - the threads must be synchronized " "using kernel facilities (which is very slow because a syscall must be " "performed). The mixed M:N scenario just combines the first and second " "approach or rely solely on kernel. Threads synchronization is a vital part " "of thread-enabled programming and its performance can affect resulting " "program a lot. Recent benchmarks on FreeBSD operating system showed that an " "improved sx_lock implementation yielded 40% speedup in _ZFS_ (a heavy sx " "user), this is in-kernel stuff but it shows clearly how important the " "performance of synchronization primitives is." msgstr "" "Потокам требуется некоторая синхронизация, и POSIX(R) предоставляет " "несколько её видов: мьютексы для взаимного исключения, блокировки чтения-" "записи для взаимного исключения с преобладанием операций чтения над записями " "и условные переменные для сигнализации об изменении состояния. Интересно " "отметить, что в API потоков POSIX(R) отсутствует поддержка семафоров. " "Реализации этих механизмов синхронизации сильно зависят от типа поддержки " "потоков, которая у нас есть. В чистой модели 1:M (пользовательское " "пространство) реализация может быть выполнена исключительно в " "пользовательском пространстве и, следовательно, быть очень быстрой (условные " "переменные, вероятно, будут реализованы с использованием сигналов, т.е. не " "быстро) и простой. В модели 1:1 ситуация также довольно ясна — потоки должны " "синхронизироваться с использованием средств ядра (что очень медленно, " "поскольку требуется выполнение системного вызова). Смешанный сценарий M:N " "просто комбинирует первый и второй подходы или полагается исключительно на " "ядро. Синхронизация потоков является важной частью программирования с " "использованием потоков, и её производительность может значительно влиять на " "итоговую программу. Недавние тесты в операционной системе FreeBSD показали, " "что улучшенная реализация `sx_lock` дала 40% прироста скорости в _ZFS_ (где " "активно используются блокировки sx), это внутренние механизмы ядра, но это " "наглядно демонстрирует, насколько важна производительность примитивов " "синхронизации." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1120 msgid "" "Threaded programs should be written with as little contention on locks as " "possible. Otherwise, instead of doing useful work the thread just waits on " "a lock. As a result of this, the most well written threaded programs show " "little locks contention." msgstr "" "Многопоточные программы должны быть написаны с минимальной конкуренцией за " "блокировки. В противном случае, вместо выполнения полезной работы поток " "просто ожидает блокировку. В результате, наиболее хорошо написанные " "многопоточные программы демонстрируют низкую конкуренцию за блокировки." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:1122 #, no-wrap msgid "Futexes introduction" msgstr "Введение в фьютексы" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1127 msgid "" "Linux(R) implements 1:1 threading, i.e. it has to use in-kernel " "synchronization primitives. As stated earlier, well written threaded " "programs have little lock contention. So a typical sequence could be " "performed as two atomic increase/decrease mutex reference counter, which is " "very fast, as presented by the following example:" msgstr "" "Linux(R) реализует 1:1 потоковую модель, то есть использует примитивы " "синхронизации в ядре. Как упоминалось ранее, хорошо написанные многопоточные " "программы имеют низкую конкуренцию за блокировки. Таким образом, типичная " "последовательность может выполняться как два атомарных увеличения/уменьшения " "счётчика ссылок мьютекса, что очень быстро, как показано в следующем примере:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:1133 #, no-wrap msgid "" "pthread_mutex_lock(&mutex);\n" "...\n" "pthread_mutex_unlock(&mutex);\n" msgstr "" "pthread_mutex_lock(&mutex);\n" "...\n" "pthread_mutex_unlock(&mutex);\n" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1136 msgid "" "1:1 threading forces us to perform two syscalls for those mutex calls, which " "is very slow." msgstr "" "1:1 threading вынуждает нас выполнять два системных вызова для этих вызовов " "мьютекса, что очень медленно." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1141 msgid "" "The solution Linux(R) 2.6 implements is called futexes. Futexes implement " "the check for contention in userspace and call kernel primitives only in a " "case of contention. Thus the typical case takes place without any kernel " "intervention. This yields reasonably fast and flexible synchronization " "primitives implementation." msgstr "" "Решение, реализованное в Linux(R) 2.6, называется фьютексы. Фьютексы " "выполняют проверку на конкуренцию в пользовательском пространстве и вызывают " "примитивы ядра только в случае конкуренции. Таким образом, типичный случай " "обходится без вмешательства ядра. Это обеспечивает достаточно быструю и " "гибкую реализацию примитивов синхронизации." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:1143 #, no-wrap msgid "Futex API" msgstr "API фьютексов" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1146 msgid "The futex syscall looks like this:" msgstr "Системный вызов futex выглядит следующим образом:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:1150 #, no-wrap msgid "int futex(void *uaddr, int op, int val, struct timespec *timeout, void *uaddr2, int val3);\n" msgstr "int futex(void *uaddr, int op, int val, struct timespec *timeout, void *uaddr2, int val3);\n" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1153 msgid "" "In this example `uaddr` is an address of the mutex in userspace, `op` is an " "operation we are about to perform and the other parameters have per-" "operation meaning." msgstr "" "В этом примере `uaddr` — это адрес мьютекса в пользовательском пространстве, " "`op` — операция, которую мы собираемся выполнить, а остальные параметры " "имеют значение, зависящее от конкретной операции." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1155 msgid "Futexes implement the following operations:" msgstr "Фьютексы реализуют следующие операции:" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1157 msgid "`FUTEX_WAIT`" msgstr "`FUTEX_WAIT`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1158 msgid "`FUTEX_WAKE`" msgstr "`FUTEX_WAKE`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1159 msgid "`FUTEX_FD`" msgstr "`FUTEX_FD`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1160 msgid "`FUTEX_REQUEUE`" msgstr "`FUTEX_REQUEUE`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1161 msgid "`FUTEX_CMP_REQUEUE`" msgstr "`FUTEX_CMP_REQUEUE`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1162 msgid "`FUTEX_WAKE_OP`" msgstr "`FUTEX_WAKE_OP`" #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:1164 #, no-wrap msgid "FUTEX_WAIT" msgstr "FUTEX_WAIT" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1169 msgid "" "This operation verifies that on address `uaddr` the value `val` is written. " "If not, `EWOULDBLOCK` is returned, otherwise the thread is queued on the " "futex and gets suspended. If the argument `timeout` is non-zero it " "specifies the maximum time for the sleeping, otherwise the sleeping is " "infinite." msgstr "" "Эта операция проверяет, что по адресу `uaddr` записано значение `val`. Если " "нет, возвращается `EWOULDBLOCK`, в противном случае поток ставится в очередь " "на фьютекс и приостанавливается. Если аргумент `timeout` не равен нулю, он " "задает максимальное время ожидания, в противном случае ожидание бесконечно." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:1171 #, no-wrap msgid "FUTEX_WAKE" msgstr "FUTEX_WAKE" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1174 msgid "" "This operation takes a futex at `uaddr` and wakes up `val` first futexes " "queued on this futex." msgstr "" "Эта операция захватывает фьютекс по адресу `uaddr` и пробуждает первые `val` " "фьютексов, ожидающих в очереди на этом фьютексе." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:1176 #, no-wrap msgid "FUTEX_FD" msgstr "FUTEX_FD" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1179 msgid "This operations associates a file descriptor with a given futex." msgstr "Эта операция связывает файловый дескриптор с заданным фьютексом." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:1181 #, no-wrap msgid "FUTEX_REQUEUE" msgstr "FUTEX_REQUEUE" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1184 msgid "" "This operation takes `val` threads queued on futex at `uaddr`, wakes them " "up, and takes `val2` next threads and requeues them on futex at `uaddr2`." msgstr "" "Эта операция берет `val` потоков, ожидающих на фьютексе по адресу `uaddr`, " "пробуждает их и берет следующие `val2` потоков, перемещая их в очередь " "фьютекса по адресу `uaddr2`." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:1186 #, no-wrap msgid "FUTEX_CMP_REQUEUE" msgstr "FUTEX_CMP_REQUEUE" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1189 msgid "" "This operation does the same as `FUTEX_REQUEUE` but it checks that `val3` " "equals to `val` first." msgstr "" "Эта операция делает то же самое, что и `FUTEX_REQUEUE`, но сначала " "проверяет, что `val3` равно `val`." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:1191 #, no-wrap msgid "FUTEX_WAKE_OP" msgstr "FUTEX_WAKE_OP" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1195 msgid "" "This operation performs an atomic operation on `val3` (which contains coded " "some other value) and `uaddr`. Then it wakes up `val` threads on futex at " "`uaddr` and if the atomic operation returned a positive number it wakes up " "`val2` threads on futex at `uaddr2`." msgstr "" "Эта операция выполняет атомарную операцию над `val3` (которая содержит " "закодированное другое значение) и `uaddr`. Затем она пробуждает `val` " "потоков на фьютексе по адресу `uaddr`, и если атомарная операция вернула " "положительное число, пробуждает `val2` потоков на фьютексе по адресу " "`uaddr2`." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1197 msgid "The operations implemented in `FUTEX_WAKE_OP`:" msgstr "Операции, реализованные в `FUTEX_WAKE_OP`:" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1199 msgid "`FUTEX_OP_SET`" msgstr "`FUTEX_OP_SET`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1200 msgid "`FUTEX_OP_ADD`" msgstr "`FUTEX_OP_ADD`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1201 msgid "`FUTEX_OP_OR`" msgstr "`FUTEX_OP_OR`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1202 msgid "`FUTEX_OP_AND`" msgstr "`FUTEX_OP_AND`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1203 msgid "`FUTEX_OP_XOR`" msgstr "`FUTEX_OP_XOR`" #. type: delimited block = 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:1208 msgid "" "There is no `val2` parameter in the futex prototype. The `val2` is taken " "from the `struct timespec *timeout` parameter for operations " "`FUTEX_REQUEUE`, `FUTEX_CMP_REQUEUE` and `FUTEX_WAKE_OP`." msgstr "" "В прототипе системного вызова futex отсутствует параметр `val2`. Значение " "`val2` берётся из параметра `struct timespec *timeout` для операций " "`FUTEX_REQUEUE`, `FUTEX_CMP_REQUEUE` и `FUTEX_WAKE_OP`." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:1211 #, no-wrap msgid "Futex emulation in FreeBSD" msgstr "Эмуляция фьютексов в FreeBSD" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1216 msgid "" "The futex emulation in FreeBSD is taken from NetBSD and further extended by " "us. It is placed in `linux_futex.c` and [.filename]#linux_futex.h# files. " "The `futex` structure looks like:" msgstr "" "Эмуляция futex в FreeBSD взята из NetBSD и дополнительно расширена нами. Она " "размещена в файлах `linux_futex.c` и [.filename]#linux_futex.h#. Структура " "`futex` выглядит следующим образом:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:1222 #, no-wrap msgid "" "struct futex {\n" " void *f_uaddr;\n" " int f_refcount;\n" msgstr "" "struct futex {\n" " void *f_uaddr;\n" " int f_refcount;\n" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:1224 #, no-wrap msgid " LIST_ENTRY(futex) f_list;\n" msgstr " LIST_ENTRY(futex) f_list;\n" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:1227 #, no-wrap msgid "" " TAILQ_HEAD(lf_waiting_paroc, waiting_proc) f_waiting_proc;\n" "};\n" msgstr "" " TAILQ_HEAD(lf_waiting_paroc, waiting_proc) f_waiting_proc;\n" "};\n" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1230 msgid "And the structure `waiting_proc` is:" msgstr "И структура `waiting_proc` выглядит следующим образом:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:1234 #, no-wrap msgid "struct waiting_proc {\n" msgstr "struct waiting_proc {\n" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:1236 #, no-wrap msgid " struct thread *wp_t;\n" msgstr " struct thread *wp_t;\n" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:1238 #, no-wrap msgid " struct futex *wp_new_futex;\n" msgstr " struct futex *wp_new_futex;\n" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:1241 #, no-wrap msgid "" " TAILQ_ENTRY(waiting_proc) wp_list;\n" "};\n" msgstr "" " TAILQ_ENTRY(waiting_proc) wp_list;\n" "};\n" #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:1244 #, no-wrap msgid "futex_get / futex_put" msgstr "futex_get / futex_put" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1248 msgid "" "A futex is obtained using the `futex_get` function, which searches a linear " "list of futexes and returns the found one or creates a new futex. When " "releasing a futex from the use we call the `futex_put` function, which " "decreases a reference counter of the futex and if the refcount reaches zero " "it is released." msgstr "" "Фьютекс получается с помощью функции `futex_get`, которая выполняет поиск в " -"линейном списке фьютексов и возвращает найденный или создает новый. При " +"линейном списке фьютексов и возвращает найденный или создаёт новый. При " "освобождении фьютекса после использования вызывается функция `futex_put`, " "которая уменьшает счетчик ссылок фьютекса, и если счетчик достигает нуля, " "фьютекс освобождается." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:1250 #, no-wrap msgid "futex_sleep" msgstr "futex_sleep" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1258 msgid "" "When a futex queues a thread for sleeping it creates a `working_proc` " "structure and puts this structure to the list inside the futex structure " "then it just performs a man:tsleep[9] to suspend the thread. The sleep can " "be timed out. After man:tsleep[9] returns (the thread was woken up or it " "timed out) the `working_proc` structure is removed from the list and is " "destroyed. All this is done in the `futex_sleep` function. If we got woken " "up from `futex_wake` we have `wp_new_futex` set so we sleep on it. This way " "the actual requeueing is done in this function." msgstr "" -"Когда фьютекс ставит поток в очередь на ожидание, он создает структуру " +"Когда фьютекс ставит поток в очередь на ожидание, он создаёт структуру " "`working_proc` и помещает эту структуру в список внутри структуры futex, " "после чего просто выполняет man:tsleep[9] для приостановки потока. Ожидание " "может быть ограничено по времени. После возврата из man:tsleep[9] (поток был " "разбужен или истекло время ожидания) структура `working_proc` удаляется из " "списка и уничтожается. Все это выполняется в функции `futex_sleep`. Если мы " "были разбужены с помощью `futex_wake`, у нас установлен `wp_new_futex`, " "поэтому мы ожидаем на нём. Таким образом, фактическое перемещение " "выполняется в этой функции." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:1260 #, no-wrap msgid "futex_wake" msgstr "futex_wake" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1268 msgid "" "Waking up a thread sleeping on a futex is performed in the `futex_wake` " "function. First in this function we mimic the strange Linux(R) behavior, " "where it wakes up N threads for all operations, the only exception is that " "the REQUEUE operations are performed on N+1 threads. But this usually does " "not make any difference as we are waking up all threads. Next in the " "function in the loop we wake up n threads, after this we check if there is a " "new futex for requeueing. If so, we requeue up to n2 threads on the new " "futex. This cooperates with `futex_sleep`." msgstr "" "Пробуждение потока, ожидающего на фьютексе, выполняется в функции " "`futex_wake`. Сначала в этой функции мы имитируем странное поведение " "Linux(R), где пробуждаются N потоков для всех операций, за исключением того, " "что операции REQUEUE выполняются на N+1 потоках. Однако обычно это не имеет " "значения, так как мы пробуждаем все потоки. Далее в функции в цикле мы " "пробуждаем n потоков, после чего проверяем, есть ли новый фьютекс для " "перестановки. Если есть, мы переставляем до n2 потоков на новый futex. Это " "взаимодействует с `futex_sleep`." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:1270 #, no-wrap msgid "futex_wake_op" msgstr "futex_wake_op" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1275 msgid "" "The `FUTEX_WAKE_OP` operation is quite complicated. First we obtain two " "futexes at addresses `uaddr` and `uaddr2` then we perform the atomic " "operation using `val3` and `uaddr2`. Then `val` waiters on the first futex " "is woken up and if the atomic operation condition holds we wake up `val2` (i." "e. `timeout`) waiter on the second futex." msgstr "" "Операция `FUTEX_WAKE_OP` довольно сложна. Сначала мы получаем два фьютекса " "по адресам `uaddr` и `uaddr2`, затем выполняем атомарную операцию с " "использованием `val3` и `uaddr2`. После этого пробуждаются `val` ожидающих " "на первом фьютексе, и если условие атомарной операции выполняется, мы " "пробуждаем `val2` (т.е. `timeout`) ожидающих на втором фьютексе." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:1277 #, no-wrap msgid "futex atomic operation" msgstr "Атомарная операция на фьютексе" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1282 msgid "" "The atomic operation takes two parameters `encoded_op` and `uaddr`. The " "encoded operation encodes the operation itself, comparing value, operation " "argument, and comparing argument. The pseudocode for the operation is like " "this one:" msgstr "" "Атомарная операция принимает два параметра `encoded_op` и `uaddr`. " "Закодированная операция включает саму операцию, сравниваемое значение, " "аргумент операции и аргумент сравнения. Псевдокод операции выглядит " "следующим образом:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:1287 #, no-wrap msgid "" "oldval = *uaddr2\n" "*uaddr2 = oldval OP oparg\n" msgstr "" "oldval = *uaddr2\n" "*uaddr2 = oldval OP oparg\n" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1291 msgid "" "And this is done atomically. First a copying in of the number at `uaddr` is " "performed and the operation is done. The code handles page faults and if no " "page fault occurs `oldval` is compared to `cmparg` argument with cmp " "comparator." msgstr "" "И это выполняется атомарно. Сначала происходит копирование числа по адресу " "`uaddr`, а затем выполняется операция. Код обрабатывает ошибки страниц, и " "если ошибки не происходит, `oldval` сравнивается с аргументом `cmparg` с " "помощью компаратора cmp." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:1293 #, no-wrap msgid "Futex locking" msgstr "Блокировка фьютекса" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1297 msgid "" "Futex implementation uses two lock lists protecting `sx_lock` and global " "locks (either Giant or another `sx_lock`). Every operation is performed " "locked from the start to the very end." msgstr "" "Реализация фьютексов использует два списка блокировок для защиты `sx_lock` и " "глобальных блокировок (либо Giant, либо другой `sx_lock`). Каждая операция " "выполняется заблокированной от начала до самого конца." #. type: Title === #: documentation/content/en/articles/linux-emulation/_index.adoc:1299 #, no-wrap msgid "Various syscalls implementation" msgstr "Реализация различных системных вызовов" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1302 msgid "" "In this section I am going to describe some smaller syscalls that are worth " "mentioning because their implementation is not obvious or those syscalls are " "interesting from other point of view." msgstr "" "В этом разделе я опишу несколько менее значимых системных вызовов, которые " "стоит упомянуть, потому что их реализация неочевидна или эти вызовы " "представляют интерес с другой точки зрения." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:1304 #, no-wrap msgid "*at family of syscalls" msgstr "*семейство системных вызовов at" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1313 msgid "" "During development of Linux(R) 2.6.16 kernel, the *at syscalls were added. " "Those syscalls (`openat` for example) work exactly like their at-less " "counterparts with the slight exception of the `dirfd` parameter. This " "parameter changes where the given file, on which the syscall is to be " "performed, is. When the `filename` parameter is absolute `dirfd` is ignored " "but when the path to the file is relative, it comes to the play. The " "`dirfd` parameter is a directory relative to which the relative pathname is " "checked. The `dirfd` parameter is a file descriptor of some directory or " "`AT_FDCWD`. So for example the `openat` syscall can be like this:" msgstr "" "Во время разработки ядра Linux(R) 2.6.16 были добавлены *at-системные " "вызовы. Эти системные вызовы (например, `openat`) работают точно так же, как " "их аналоги без at, за исключением параметра `dirfd`. Этот параметр " "определяет местоположение файла, над которым выполняется системный вызов. " "Если параметр `filename` является абсолютным, `dirfd` игнорируется, но если " "путь к файлу относительный, `dirfd` вступает в игру. Параметр `dirfd` " "представляет собой каталог, относительно которого проверяется относительный " "путь. Параметр `dirfd` является файловым дескриптором некоторого каталога " "или `AT_FDCWD`. Например, системный вызов `openat` может выглядеть следующим " "образом:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:1317 #, no-wrap msgid "file descriptor 123 = /tmp/foo/, current working directory = /tmp/\n" msgstr "file descriptor 123 = /tmp/foo/, current working directory = /tmp/\n" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:1322 #, no-wrap msgid "" "openat(123, /tmp/bah\\, flags, mode)\t/* opens /tmp/bah */\n" "openat(123, bah\\, flags, mode)\t\t/* opens /tmp/foo/bah */\n" "openat(AT_FDWCWD, bah\\, flags, mode)\t/* opens /tmp/bah */\n" "openat(stdio, bah\\, flags, mode)\t/* returns error because stdio is not a directory */\n" msgstr "" "openat(123, /tmp/bah\\, flags, mode)\t/* opens /tmp/bah */\n" "openat(123, bah\\, flags, mode)\t\t/* opens /tmp/foo/bah */\n" "openat(AT_FDWCWD, bah\\, flags, mode)\t/* opens /tmp/bah */\n" "openat(stdio, bah\\, flags, mode)\t/* returns error because stdio is not a directory */\n" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1331 msgid "" "This infrastructure is necessary to avoid races when opening files outside " "the working directory. Imagine that a process consists of two threads, " "thread A and thread B. Thread A issues `open(./tmp/foo/bah., flags, mode)` " "and before returning it gets preempted and thread B runs. Thread B does not " "care about the needs of thread A and renames or removes [.filename]#/tmp/foo/" "#. We got a race. To avoid this we can open [.filename]#/tmp/foo# and use " "it as `dirfd` for `openat` syscall. This also enables user to implement per-" "thread working directories." msgstr "" "Эта инфраструктура необходима для избежания состояний гонки при открытии " "файлов вне рабочего каталога. Представьте, что процесс состоит из двух " "потоков, потока A и потока B. Поток A выполняет `open(./tmp/foo/bah., flags, " "mode)`, и перед возвратом управления он вытесняется, и начинает выполняться " "поток B. Поток B не учитывает потребности потока A и переименовывает или " "удаляет [.filename]#/tmp/foo/#. Возникает состояние гонки. Чтобы избежать " "этого, мы можем открыть [.filename]#/tmp/foo# и использовать его как `dirfd` " "для системного вызова `openat`. Это также позволяет пользователю реализовать " "рабочие каталоги для каждого потока." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1334 msgid "" "Linux(R) family of *at syscalls contains: `linux_openat`, `linux_mkdirat`, " "`linux_mknodat`, `linux_fchownat`, `linux_futimesat`, `linux_fstatat64`, " "`linux_unlinkat`, `linux_renameat`, `linux_linkat`, `linux_symlinkat`, " "`linux_readlinkat`, `linux_fchmodat` and `linux_faccessat`. All these are " "implemented using the modified man:namei[9] routine and simple wrapping " "layer." msgstr "" "Семейство *at системных вызовов Linux(R) включает: `linux_openat`, " "`linux_mkdirat`, `linux_mknodat`, `linux_fchownat`, `linux_futimesat`, " "`linux_fstatat64`, `linux_unlinkat`, `linux_renameat`, `linux_linkat`, " "`linux_symlinkat`, `linux_readlinkat`, `linux_fchmodat` и `linux_faccessat`. " "Все они реализованы с использованием модифицированной функции man:namei[9] и " "простого слоя обёртки." #. type: Title ===== #: documentation/content/en/articles/linux-emulation/_index.adoc:1336 #, no-wrap msgid "Implementation" msgstr "Реализация" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1344 msgid "" "The implementation is done by altering the man:namei[9] routine (described " "above) to take additional parameter `dirfd` in its `nameidata` structure, " "which specifies the starting point of the pathname lookup instead of using " "the current working directory every time. The resolution of `dirfd` from " "file descriptor number to a vnode is done in native *at syscalls. When " "`dirfd` is `AT_FDCWD` the `dvp` entry in `nameidata` structure is `NULL` but " "when `dirfd` is a different number we obtain a file for this file " "descriptor, check whether this file is valid and if there is vnode attached " "to it then we get a vnode. Then we check this vnode for being a directory. " "In the actual man:namei[9] routine we simply substitute the `dvp` vnode for " "`dp` variable in the man:namei[9] function, which determines the starting " "point. The man:namei[9] is not used directly but via a trace of different " "functions on various levels. For example the `openat` goes like this:" msgstr "" "Реализация выполнена путем изменения функции man:namei[9] (описанной выше) " "для приема дополнительного параметра `dirfd` в структуре `nameidata`, " "который указывает начальную точку для поиска пути вместо использования " "текущего рабочего каталога каждый раз. Преобразование `dirfd` из номера " "файлового дескриптора в vnode выполняется в нативных *at-системных вызовах. " "Когда `dirfd` равен `AT_FDCWD`, запись `dvp` в структуре `nameidata` имеет " "значение `NULL`, но если `dirfd` представляет другой номер, мы получаем файл " "по этому дескриптору, проверяем его валидность и, если к нему прикреплен " "vnode, получаем этот vnode. Затем проверяем, является ли этот vnode " "каталогом. В самой функции man:namei[9] мы просто заменяем vnode `dvp` на " "переменную `dp` в функции man:namei[9], которая определяет начальную точку. " "Функция man:namei[9] используется не напрямую, а через цепочку различных " "функций на разных уровнях. Например, `openat` работает следующим образом:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-emulation/_index.adoc:1348 #, no-wrap msgid "openat() --> kern_openat() --> vn_open() -> namei()\n" msgstr "openat() --> kern_openat() --> vn_open() -> namei()\n" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1354 msgid "" "For this reason `kern_open` and `vn_open` must be altered to incorporate the " "additional `dirfd` parameter. No compat layer is created for those because " "there are not many users of this and the users can be easily converted. " "This general implementation enables FreeBSD to implement their own *at " "syscalls. This is being discussed right now." msgstr "" "По этой причине `kern_open` и `vn_open` должны быть изменены для включения " "дополнительного параметра `dirfd`. Слой совместимости для них не создаётся, " "так как пользователей этих функций немного и их можно легко адаптировать. " "Данная общая реализация позволяет FreeBSD реализовать свои собственные *at-" "системные вызовы. Это обсуждается в настоящее время." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:1356 #, no-wrap msgid "Ioctl" msgstr "Ioctl" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1370 msgid "" "The ioctl interface is quite fragile due to its generality. We have to bear " "in mind that devices differ between Linux(R) and FreeBSD so some care must " "be applied to do ioctl emulation work right. The ioctl handling is " "implemented in [.filename]#linux_ioctl.c#, where `linux_ioctl` function is " "defined. This function simply iterates over sets of ioctl handlers to find " "a handler that implements a given command. The ioctl syscall has three " "parameters, the file descriptor, command and an argument. The command is a " "16-bit number, which in theory is divided into high 8 bits determining class " "of the ioctl command and low 8 bits, which are the actual command within the " "given set. The emulation takes advantage of this division. We implement " "handlers for each set, like `sound_handler` or `disk_handler`. Each handler " "has a maximum command and a minimum command defined, which is used for " "determining what handler is used. There are slight problems with this " "approach because Linux(R) does not use the set division consistently so " "sometimes ioctls for a different set are inside a set they should not belong " "to (SCSI generic ioctls inside cdrom set, etc.). FreeBSD currently does not " "implement many Linux(R) ioctls (compared to NetBSD, for example) but the " "plan is to port those from NetBSD. The trend is to use Linux(R) ioctls even " "in the native FreeBSD drivers because of the easy porting of applications." msgstr "" "Интерфейс ioctl довольно хрупок из-за своей обобщённости. Необходимо " "учитывать, что устройства в Linux(R) и FreeBSD различаются, поэтому " "требуется особая осторожность для корректной работы эмуляции ioctl. " "Обработка ioctl реализована в файле [.filename]#linux_ioctl.c#, где " "определена функция `linux_ioctl`. Эта функция просто перебирает наборы " "обработчиков ioctl, чтобы найти обработчик, реализующий данную команду. " "Системный вызов ioctl имеет три параметра: файловый дескриптор, команду и " "аргумент. Команда представляет собой 16-битное число, которое теоретически " "делится на старшие 8 бит, определяющие класс команды ioctl, и младшие 8 бит, " "которые являются конкретной командой в данном наборе. Эмуляция использует " "это разделение. Реализованы обработчики для каждого набора, такие как " "`sound_handler` или `disk_handler`. Каждый обработчик имеет определённые " "максимальную и минимальную команды, которые используются для выбора нужного " "обработчика. Существуют небольшие проблемы с этим подходом, поскольку " "Linux(R) не всегда последовательно использует разделение на наборы, поэтому " "иногда ioctls для другого набора оказываются внутри набора, к которому они " "не должны принадлежать (например, SCSI generic ioctls внутри набора cdrom и " "т.д.). В настоящее время FreeBSD реализует не так много ioctls Linux(R) (по " "сравнению с NetBSD, например), но планируется перенести их из NetBSD. " "Тенденция такова, что ioctls Linux(R) используются даже в родных драйверах " "FreeBSD для упрощения портирования приложений." #. type: Title ==== #: documentation/content/en/articles/linux-emulation/_index.adoc:1372 #, no-wrap msgid "Debugging" msgstr "Отладка" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1379 msgid "" "Every syscall should be debuggable. For this purpose we introduce a small " "infrastructure. We have the ldebug facility, which tells whether a given " "syscall should be debugged (settable via a sysctl). For printing we have " "LMSG and ARGS macros. Those are used for altering a printable string for " "uniform debugging messages." msgstr "" "Каждый системный вызов должен поддерживать отладку. Для этой цели мы вводим " "небольшую инфраструктуру. У нас есть механизм `ldebug`, который определяет, " "нужно ли отлаживать данный системный вызов (настраивается через `sysctl`). " "Для вывода сообщений используются макросы `LMSG` и `ARGS`. Они применяются " "для форматирования строк вывода с целью создания единообразных отладочных " "сообщений." #. type: Title == #: documentation/content/en/articles/linux-emulation/_index.adoc:1381 #, no-wrap msgid "Conclusion" msgstr "Заключение" #. type: Title === #: documentation/content/en/articles/linux-emulation/_index.adoc:1384 #, no-wrap msgid "Results" msgstr "Результаты" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1390 msgid "" "As of April 2007 the Linux(R) emulation layer is capable of emulating the " "Linux(R) 2.6.16 kernel quite well. The remaining problems concern futexes, " "unfinished *at family of syscalls, problematic signals delivery, missing " "`epoll` and `inotify` and probably some bugs we have not discovered yet. " "Despite this we are capable of running basically all the Linux(R) programs " "included in FreeBSD Ports Collection with Fedora Core 4 at 2.6.16 and there " "are some rudimentary reports of success with Fedora Core 6 at 2.6.16. The " "Fedora Core 6 linux_base was recently committed enabling some further " "testing of the emulation layer and giving us some more hints where we should " "put our effort in implementing missing stuff." msgstr "" "По состоянию на апрель 2007 года уровень эмуляции Linux(R) способен " "достаточно хорошо эмулировать ядро Linux(R) 2.6.16. Оставшиеся проблемы " "касаются фьютексов, незавершённого семейства системных вызовов *at, " "проблематичной доставки сигналов, отсутствия `epoll` и `inotify`, а также, " "вероятно, некоторых ошибок, которые мы ещё не обнаружили. Несмотря на это, " "мы способны запускать практически все программы Linux(R), включённые в " "Коллекцию портов FreeBSD, с Fedora Core 4 на ядре 2.6.16, а также есть " "некоторые предварительные сообщения об успешной работе с Fedora Core 6 на " "ядре 2.6.16. Недавно был добавлен linux_base Fedora Core 6, что позволило " "провести дополнительные тестирования уровня эмуляции и дало нам больше " "подсказок, куда следует направить усилия для реализации недостающих функций." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1394 msgid "" "We are able to run the most used applications like package:www/linux-" "firefox[], package:net-im/skype[] and some games from the Ports Collection. " "Some of the programs exhibit bad behavior under 2.6 emulation but this is " "currently under investigation and hopefully will be fixed soon. The only " "big application that is known not to work is the Linux(R) Java(TM) " "Development Kit and this is because of the requirement of `epoll` facility " "which is not directly related to the Linux(R) kernel 2.6." msgstr "" "Мы можем запускать наиболее популярные приложения, такие как package:www/" "linux-firefox[], package:net-im/skype[], и некоторые игры из Коллекции " "портов. Некоторые программы демонстрируют некорректное поведение при " "эмуляции 2.6, но это в настоящее время исследуется, и, надеемся, скоро будет " "исправлено. Единственное крупное приложение, которое, как известно, не " "работает, — это Linux(R) Java(TM) Development Kit, и это связано с " "требованием функции `epoll`, которая не имеет прямого отношения к ядру " "Linux(R) 2.6." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1397 msgid "" "We hope to enable 2.6.16 emulation by default some time after FreeBSD 7.0 is " "released at least to expose the 2.6 emulation parts for some wider testing. " "Once this is done we can switch to Fedora Core 6 linux_base, which is the " "ultimate plan." msgstr "" "Мы надеемся включить эмуляцию 2.6.16 по умолчанию через некоторое время " "после выхода FreeBSD 7.0, по крайней мере, чтобы открыть части эмуляции 2.6 " "для более широкого тестирования. Как только это будет сделано, мы сможем " "перейти на Fedora Core 6 linux_base, что является конечной целью." #. type: Title === #: documentation/content/en/articles/linux-emulation/_index.adoc:1399 #, no-wrap msgid "Future work" msgstr "Будущие работы" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1402 msgid "" "Future work should focus on fixing the remaining issues with futexes, " "implement the rest of the *at family of syscalls, fix the signal delivery " "and possibly implement the `epoll` and `inotify` facilities." msgstr "" "Будущая работа должна быть сосредоточена на исправлении оставшихся проблем с " "фьютексами, реализации оставшихся системных вызовов семейства *at, " "исправлении доставки сигналов и, возможно, реализации механизмов `epoll` и " "`inotify`." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1404 msgid "" "We hope to be able to run the most important programs flawlessly soon, so we " "will be able to switch to the 2.6 emulation by default and make the Fedora " "Core 6 the default linux_base because our currently used Fedora Core 4 is " "not supported any more." msgstr "" "Мы надеемся вскоре добиться безупречной работы наиболее важных программ, " "чтобы можно было по умолчанию переключиться на эмуляцию 2.6 и сделать Fedora " "Core 6 базовой версией linux_base, поскольку используемая в настоящее время " "Fedora Core 4 больше не поддерживается." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1408 msgid "" "The other possible goal is to share our code with NetBSD and DragonflyBSD. " "NetBSD has some support for 2.6 emulation but its far from finished and not " "really tested. DragonflyBSD has expressed some interest in porting the 2.6 " "improvements." msgstr "" "Другая возможная цель — поделиться нашим кодом с NetBSD и DragonflyBSD. " "NetBSD имеет некоторую поддержку эмуляции 2.6, но она далека от завершения и " "не была должным образом протестирована. DragonflyBSD выразила некоторую " "заинтересованность в переносе улучшений версии 2.6." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1413 msgid "" "Generally, as Linux(R) develops we would like to keep up with their " "development, implementing newly added syscalls. Splice comes to mind " "first. Some already implemented syscalls are also suboptimal, for example " "`mremap` and others. Some performance improvements can also be made, finer " "grained locking and others." msgstr "" "В целом, по мере развития Linux(R) мы хотели бы идти в ногу с их " "разработкой, реализуя новые системные вызовы. В первую очередь на ум " "приходит `splice`. Некоторые уже реализованные системные вызовы также " "неоптимальны, например `mremap` и другие. Также можно внести некоторые " "улучшения производительности, такие как более детальная блокировка и другие." #. type: Title === #: documentation/content/en/articles/linux-emulation/_index.adoc:1415 #, no-wrap msgid "Team" msgstr "Команда" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1418 msgid "I cooperated on this project with (in alphabetical order):" msgstr "Я сотрудничал в этом проекте с (в алфавитном порядке):" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1420 msgid "`{jhb}`" msgstr "`{jhb}`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1421 msgid "`{kib}`" msgstr "`{kib}`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1422 msgid "Emmanuel Dreyfus" msgstr "Emmanuel Dreyfus" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1423 msgid "Scot Hetzel" msgstr "Scot Hetzel" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1424 msgid "`{jkim}`" msgstr "`{jkim}`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1425 msgid "`{netchild}`" msgstr "`{netchild}`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1426 msgid "`{ssouhlal}`" msgstr "`{ssouhlal}`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1427 msgid "Li Xiao" msgstr "Li Xiao" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1428 msgid "`{davidxu}`" msgstr "`{davidxu}`" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1430 msgid "" "I would like to thank all those people for their advice, code reviews and " "general support." msgstr "" "Я хотел бы поблагодарить всех этих людей за их советы, рецензирование кода и " "общую поддержку." #. type: Title == #: documentation/content/en/articles/linux-emulation/_index.adoc:1432 #, no-wrap msgid "Literatures" msgstr "Литература" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1435 msgid "" "Marshall Kirk McKusick - George V. Neville-Neil. Design and Implementation " "of the FreeBSD operating system. Addison-Wesley, 2005." msgstr "" "Marshall Kirk McKusick - George V. Neville-Neil. Design and Implementation " "of the FreeBSD operating system. Addison-Wesley, 2005 год." #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1436 msgid "https://tldp.org[https://tldp.org]" msgstr "https://tldp.org[https://tldp.org]" #. type: Plain text #: documentation/content/en/articles/linux-emulation/_index.adoc:1436 msgid "https://www.kernel.org[https://www.kernel.org]" msgstr "https://www.kernel.org[https://www.kernel.org]" diff --git a/documentation/content/ru/articles/linux-users/_index.adoc b/documentation/content/ru/articles/linux-users/_index.adoc index df3c6aaaa7..bcd6359bc8 100644 --- a/documentation/content/ru/articles/linux-users/_index.adoc +++ b/documentation/content/ru/articles/linux-users/_index.adoc @@ -1,337 +1,337 @@ --- authors: - author: 'John Ferrell' copyright: '2008 The FreeBSD Documentation Project' description: 'Этот документ предназначен для быстрого ознакомления с основами FreeBSD пользователей Linux® среднего и продвинутого уровня.' tags: ["Quickstart", "guide", "Linux", "FreeBSD"] title: 'Быстрое руководство по FreeBSD для пользователей Linux®' trademarks: ["freebsd", "intel", "redhat", "linux", "unix", "general"] --- = Быстрое руководство по FreeBSD для пользователей Linux(R) :doctype: article :toc: macro :toclevels: 1 :icons: font :sectnums: :sectnumlevels: 6 :source-highlighter: rouge :experimental: :images-path: articles/linux-users/ ifdef::env-beastie[] ifdef::backend-html5[] include::shared/authors.adoc[] include::shared/mirrors.adoc[] include::shared/releases.adoc[] include::shared/attributes/attributes-{{% lang %}}.adoc[] include::shared/{{% lang %}}/teams.adoc[] include::shared/{{% lang %}}/mailing-lists.adoc[] include::shared/{{% lang %}}/urls.adoc[] :imagesdir: ../../../images/{images-path} endif::[] ifdef::backend-pdf,backend-epub3[] include::../../../../shared/asciidoctor.adoc[] endif::[] endif::[] ifndef::env-beastie[] include::../../../../../shared/asciidoctor.adoc[] endif::[] [.abstract-title] Аннотация Этот документ предназначен для быстрого ознакомления с основами FreeBSD пользователей Linux(R) среднего и продвинутого уровня. ''' toc::[] [[intro]] == Введение В этом документе освещаются некоторые технические различия между FreeBSD и Linux(R), чтобы пользователи Linux(R) среднего и продвинутого уровней могли быстро ознакомиться с основами FreeBSD. Этот документ предполагает, что FreeBSD уже установлена. Для получения помощи по процессу установки обратитесь к главе extref:{handbook}bsdinstall[Установка FreeBSD, bsdinstall] Руководства FreeBSD. [[shells]] == Стандартная оболочка -Пользователи Linux(R) часто удивляются, обнаружив, что Bash не является оболочкой по умолчанию в FreeBSD. На самом деле, Bash не включён в стандартную установку. Вместо этого используется совместимая с Bourne shell оболочка man:sh[1] в качестве оболочки пользователя по умолчанию. Оболочка root — это man:tcsh[1] по умолчанию в FreeBSD 13 и более ранних версиях и man:sh[1] в FreeBSD 14 и позднее. Оболочка man:sh[1] очень похожа на Bash, но имеет гораздо меньший набор возможностей. Как правило, скрипты, написанные для man:sh[1], будут работать в Bash, но обратное не всегда верно. +Пользователи Linux(R) часто удивляются, обнаружив, что Bash не является оболочкой по умолчанию в FreeBSD. На самом деле, Bash не включён в стандартную установку. Вместо этого используется совместимая с POSIX(R) shell оболочка man:sh[1] в качестве оболочки пользователя по умолчанию. Оболочка root — это man:tcsh[1] по умолчанию в FreeBSD 13 и более ранних версиях и man:sh[1] в FreeBSD 14 и позднее. Оболочка man:sh[1] очень похожа на Bash, но имеет гораздо меньший набор возможностей. Как правило, скрипты, написанные для man:sh[1], будут работать в Bash, но обратное не всегда верно. Однако Bash и другие оболочки доступны для установки через extref:{handbook}ports[Коллекцию портов и пакетов FreeBSD, ports]. После установки другой оболочки используйте man:chsh[1], чтобы изменить оболочку пользователя по умолчанию. Рекомендуется оставить оболочку пользователя `root` без изменений, поскольку оболочки, не входящие в базовую поставку, устанавливаются в [.filename]#/usr/local/bin#. В случае возникновения проблемы файловая система, в которой находится [.filename]#/usr/local/bin#, может быть не смонтирована. В такой ситуации у `root` не будет доступа к своей оболочке по умолчанию, что помешает ему войти в систему и устранить проблему. [[software]] == Пакеты и порты: установка программ в FreeBSD FreeBSD предоставляет два метода установки приложений: бинарные пакеты и скомпилированные порты. Каждый метод имеет свои преимущества: .Бинарные пакеты * Быстрая установка по сравнению с компиляцией крупных приложений. * Не требует понимания того, как компилировать программное обеспечение. * Нет необходимости устанавливать компилятор. .Порты * Возможность настройки параметров установки. * Могут быть применены пользовательские патчи. Если установка приложения не требует дополнительной собственной настройки, достаточно установить пакет. Собирайте порт, если приложению требуется изменение параметров, заданных в пакетах по умолчанию. При необходимости собственный пакет можно собрать из портов с помощью `make package`. Полный список всех доступных портов и пакетов можно найти https://ports.freebsd.org[здесь]. [[packages]] === Пакеты Пакеты — это предварительно скомпилированные приложения, эквиваленты файлов [.filename]#.deb# в системах на основе Debian/Ubuntu и файлов [.filename]#.rpm# в системах на основе Red Hat/Fedora. Пакеты устанавливаются с помощью `pkg`. Например, следующая команда устанавливает Apache 2.4: [source, shell] .... # pkg install apache24 .... Для получения дополнительной информации о пакетах обратитесь к разделу 4.4 Руководства FreeBSD: extref:{handbook}ports[Использование pkg для управления бинарными пакетами, pkgng-intro]. [[ports]] === Порты Коллекция портов FreeBSD — это набор [.filename]#Makefile# и патчей, специально адаптированных для установки приложений из исходного кода в FreeBSD. При установке порта система загрузит исходный код, применит необходимые патчи, скомпилирует код и установит приложение вместе с требуемыми зависимостями. Коллекция портов, иногда называемая деревом портов, может быть установлена в [.filename]#/usr/ports# с помощью link:{handbook}mirrors/#git[Git]. Подробные инструкции по установке Коллекции портов можно найти в extref:{handbook}ports[разделе 4.5.1, ports-using-installation-methods] Руководства FreeBSD. Для сборки порта перейдите в его каталог и запустите процесс сборки. В следующем примере устанавливается Apache 2.4 из коллекции портов: [source, shell] .... # cd /usr/ports/www/apache24 # make install clean .... Преимущество использования портов для установки программного обеспечения заключается в возможности настройки параметров установки. В этом примере указано, что также должен быть установлен модуль mod_ldap: [source, shell] .... # cd /usr/ports/www/apache24 # make WITH_LDAP="YES" install clean .... Обратитесь к разделу extref:{handbook}ports[Использование коллекции портов, ports-using] для получения дополнительной информации. [[startup]] == Загрузка системы Многие дистрибутивы Linux(R) используют систему инициализации SysV, тогда как FreeBSD использует традиционный BSD-стиль man:init[8]. В BSD-стиле man:init[8] нет уровней запуска (run-levels), и файл [.filename]#/etc/inittab# отсутствует. Вместо этого запуск системы управляется сценариями man:rc[8]. При загрузке системы [.filename]#/etc/rc# читает [.filename]#/etc/rc.conf# и [.filename]#/etc/defaults/rc.conf#, чтобы определить, какие службы должны быть запущены. Указанные службы затем запускаются путем выполнения соответствующих сценариев инициализации, расположенных в [.filename]#/etc/rc.d/# и [.filename]#/usr/local/etc/rc.d/#. Эти сценарии аналогичны сценариям, расположенным в [.filename]#/etc/init.d/# в системах Linux(R). Скрипты, расположенные в [.filename]#/etc/rc.d/#, предназначены для приложений, входящих в "базовую" систему, таких как man:cron[8], man:sshd[8] и man:syslog[3]. Скрипты в [.filename]#/usr/local/etc/rc.d/# предназначены для пользовательских приложений, таких как Apache и Squid. Поскольку FreeBSD разрабатывается как полноценная операционная система, пользовательские приложения не считаются частью «базовой» системы. Пользовательские приложения обычно устанавливаются с помощью extref:{handbook}ports[Пакетов или Портов, ports-using]. Чтобы отделить их от базовой системы, пользовательские приложения устанавливаются в [.filename]#/usr/local/#. Таким образом, исполняемые файлы пользовательских приложений находятся в [.filename]#/usr/local/bin/#, конфигурационные файлы — в [.filename]#/usr/local/etc/# и так далее. Сервисы включаются путем добавления соответствующей записи в файл [.filename]#/etc/rc.conf#. Системные параметры по умолчанию находятся в файле [.filename]#/etc/defaults/rc.conf#, а настройки по умолчанию переопределяются параметрами из файла [.filename]#/etc/rc.conf#. Подробнее о доступных параметрах можно узнать в man:rc.conf[5]. При установке дополнительных приложений ознакомьтесь с сообщением установки, чтобы определить, как включить связанные сервисы. Следующие записи в [.filename]#/etc/rc.conf# включают man:sshd[8], активируют Apache 2.4 и указывают, что Apache должен запускаться с SSL. [.programlisting] .... # enable SSHD sshd_enable="YES" # enable Apache with SSL apache24_enable="YES" apache24_flags="-DSSL" .... После включения службы в [.filename]#/etc/rc.conf# её можно запустить без перезагрузки системы: [source, shell] .... # service sshd start # service apache24 start .... Если служба не была включена, её можно запустить из командной строки с помощью `onestart`: [source, shell] .... # service sshd onestart .... [[network]] == Настройка сети Вместо общего идентификатора _ethX_, который используется в Linux(R) для обозначения сетевого интерфейса, FreeBSD использует имя драйвера с последующим числом. Следующий вывод из man:ifconfig[8] показывает два сетевых интерфейса Intel(R) Pro 1000 ([.filename]#em0# и [.filename]#em1#): [source, shell] .... % ifconfig em0: flags=8843 mtu 1500 options=b inet 10.10.10.100 netmask 0xffffff00 broadcast 10.10.10.255 ether 00:50:56:a7:70:b2 media: Ethernet autoselect (1000baseTX ) status: active em1: flags=8843 mtu 1500 options=b inet 192.168.10.222 netmask 0xffffff00 broadcast 192.168.10.255 ether 00:50:56:a7:03:2b media: Ethernet autoselect (1000baseTX ) status: active .... IP-адрес может быть назначен интерфейсу с помощью man:ifconfig[8]. Чтобы настройки сохранялись после перезагрузки, конфигурация IP должна быть указана в [.filename]#/etc/rc.conf#. Следующие записи в [.filename]#/etc/rc.conf# задают имя хоста, IP-адрес и шлюз по умолчанию: [.programlisting] .... hostname="server1.example.com" ifconfig_em0="inet 10.10.10.100 netmask 255.255.255.0" defaultrouter="10.10.10.1" .... Используйте следующие записи для настройки интерфейса через DHCP: [.programlisting] .... hostname="server1.example.com" ifconfig_em0="DHCP" .... [[firewall]] == Firewall FreeBSD не использует Linux(R) IPTABLES для своего межсетевого экрана. Вместо этого FreeBSD предлагает выбор из трёх межсетевых экранов на уровне ядра: * extref:{handbook}firewalls[PF, firewalls-pf] * extref:{handbook}firewalls[IPFILTER, firewalls-ipf] * extref:{handbook}firewalls[IPFW, firewalls-ipfw] PF разработан проектом OpenBSD и портирован в FreeBSD. PF был создан как замена для IPFILTER, и его синтаксис схож с синтаксисом IPFILTER. PF может использоваться совместно с man:altq[4] для обеспечения функций QoS. Этот пример записи PF разрешает входящий SSH: [.programlisting] .... pass in on $ext_if inet proto tcp from any to ($ext_if) port 22 .... IPFILTER — это приложение для межсетевого экрана, разработанное Дарреном Ридом. Оно не является специфичным для FreeBSD и было портировано на несколько операционных систем, включая NetBSD, OpenBSD, SunOS, HP/UX и Solaris. Синтаксис IPFILTER для разрешения входящего SSH: [.programlisting] .... pass in on $ext_if proto tcp from any to any port = 22 .... IPFW — это межсетевой экран, разработанный и поддерживаемый FreeBSD. Он может быть использован совместно с man:dummynet[4] для обеспечения возможностей управления трафиком и имитации различных типов сетевых соединений. Синтаксис IPFW для разрешения входящего SSH будет следующим: [.programlisting] .... ipfw add allow tcp from any to me 22 in via $ext_if .... [[updates]] == Обновление FreeBSD Существует два метода обновления системы FreeBSD: из исходного кода или бинарные обновления. Обновление из исходного кода — это наиболее сложный метод обновления, но он предоставляет наибольшую гибкость. Процесс включает синхронизацию локальной копии исходного кода FreeBSD с репозиторием FreeBSD Git. После того как локальный исходный код обновлён, можно скомпилировать новую версию ядра и пользовательского пространства. Двоичные обновления аналогичны использованию `yum` или `apt-get` для обновления системы Linux(R). В FreeBSD, man:freebsd-update[8] может быть использован для получения и установки новых двоичных обновлений. Эти обновления могут быть запланированы с помощью man:cron[8]. [NOTE] ==== При использовании man:cron[8] для планирования обновлений используйте `freebsd-update cron` в man:crontab[1], чтобы снизить вероятность одновременного скачивания обновлений большим количеством машин: [.programlisting] .... 0 3 * * * root /usr/sbin/freebsd-update cron .... ==== Для получения дополнительной информации об обновлениях исходного кода и бинарных обновлениях обратитесь к extref:{handbook}cutting-edge[главе об обновлениях, updating-upgrading-freebsdupdate] в Руководстве FreeBSD. [[procfs]] == procfs: ушёл, но не забыт В некоторых дистрибутивах Linux(R) можно посмотреть файл [.filename]#/proc/sys/net/ipv4/ip_forward#, чтобы определить, включена ли IP-маршрутизация. В FreeBSD вместо этого используется man:sysctl[8] для просмотра этого и других системных параметров. Например, используйте следующую команду, чтобы определить, включена ли IP-переадресация в системе FreeBSD: [source, shell] .... % sysctl net.inet.ip.forwarding net.inet.ip.forwarding: 0 .... Используйте `-a` для вывода всех системных настроек: [source, shell] .... % sysctl -a | more .... Если приложению требуется procfs, добавьте следующую запись в [.filename]#/etc/fstab#: [source, shell] .... proc /proc procfs rw,noauto 0 0 .... Добавление `noauto` предотвратит автоматическое монтирование [.filename]#/proc# при загрузке. Чтобы подключить файловую систему без перезагрузки: [source, shell] .... # mount /proc .... [[commands]] == Распространенные команды Некоторые эквиваленты распространённых команд приведены ниже: [.informaltable] [cols="1,1,1", frame="none", options="header"] |=== | Команда Linux(R) (Red Hat/Debian) | Эквивалент FreeBSD | Назначение |`yum install _package_` / `apt-get install _package_` |`pkg install _package_` |Установить пакет из удалённого репозитория |`rpm -ivh _package_` / `dpkg -i _package_` |`pkg add _package_` |Установить локальный пакет |`rpm -qa` / `dpkg -l` |`pkg info` |Список установленных пакетов |`lspci` |`pciconf` |Перечислить устройства PCI |`lsmod` |`kldstat` |Перечислить загруженные модули ядра |`modprobe` |`kldload` / `kldunload` |Загрузка/выгрузка модулей ядра |`strace` |`truss` |Трассировка системных вызовов |=== [[conclusion]] == Заключение Этот документ предоставил обзор FreeBSD. Для более детального изучения этих тем, а также многих других, не рассмотренных в данном документе, обратитесь к extref:{handbook}[Руководству FreeBSD]. diff --git a/documentation/content/ru/articles/linux-users/_index.po b/documentation/content/ru/articles/linux-users/_index.po index bb025573fa..c70d96c723 100644 --- a/documentation/content/ru/articles/linux-users/_index.po +++ b/documentation/content/ru/articles/linux-users/_index.po @@ -1,987 +1,987 @@ # SOME DESCRIPTIVE TITLE # Copyright (C) YEAR The FreeBSD Project # This file is distributed under the same license as the FreeBSD Documentation package. # Vladlen Popolitov , 2025, 2026. msgid "" msgstr "" "Project-Id-Version: FreeBSD Documentation VERSION\n" -"POT-Creation-Date: 2025-11-08 16:17+0000\n" -"PO-Revision-Date: 2026-03-08 09:11+0000\n" +"POT-Creation-Date: 2026-05-09 23:29+0100\n" +"PO-Revision-Date: 2026-05-11 04:45+0000\n" "Last-Translator: Vladlen Popolitov \n" "Language-Team: Russian \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "X-Generator: Weblate 4.17\n" #. type: YAML Front Matter: description #: documentation/content/en/articles/linux-users/_index.adoc:1 #, no-wrap msgid "This document is intended to quickly familiarize intermediate to advanced Linux® users with the basics of FreeBSD." msgstr "Этот документ предназначен для быстрого ознакомления с основами FreeBSD пользователей Linux® среднего и продвинутого уровня." #. type: YAML Front Matter: title #: documentation/content/en/articles/linux-users/_index.adoc:1 #, no-wrap msgid "FreeBSD Quickstart Guide for Linux® Users" msgstr "Быстрое руководство по FreeBSD для пользователей Linux®" #. type: Title = #: documentation/content/en/articles/linux-users/_index.adoc:11 #, no-wrap msgid "FreeBSD Quickstart Guide for Linux(R) Users" msgstr "Быстрое руководство по FreeBSD для пользователей Linux(R)" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:44 msgid "Abstract" msgstr "Аннотация" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:46 msgid "" "This document is intended to quickly familiarize intermediate to advanced " "Linux(R) users with the basics of FreeBSD." msgstr "" "Этот документ предназначен для быстрого ознакомления с основами FreeBSD " "пользователей Linux(R) среднего и продвинутого уровня." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:48 msgid "'''" msgstr "'''" #. type: Title == #: documentation/content/en/articles/linux-users/_index.adoc:52 #, no-wrap msgid "Introduction" msgstr "Введение" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:55 msgid "" "This document highlights some of the technical differences between FreeBSD " "and Linux(R) so that intermediate to advanced Linux(R) users can quickly " "familiarize themselves with the basics of FreeBSD." msgstr "" "В этом документе освещаются некоторые технические различия между FreeBSD и " "Linux(R), чтобы пользователи Linux(R) среднего и продвинутого уровней могли " "быстро ознакомиться с основами FreeBSD." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:58 msgid "" "This document assumes that FreeBSD is already installed. Refer to the " "extref:{handbook}bsdinstall[Installing FreeBSD, bsdinstall] chapter of the " "FreeBSD Handbook for help with the installation process." msgstr "" "Этот документ предполагает, что FreeBSD уже установлена. Для получения " -"помощи по процессу установки обратитесь к главе extref:{handbook}bsdinstall[" -"Установка FreeBSD, bsdinstall] Руководства FreeBSD." +"помощи по процессу установки обратитесь к главе extref:{handbook}" +"bsdinstall[Установка FreeBSD, bsdinstall] Руководства FreeBSD." #. type: Title == #: documentation/content/en/articles/linux-users/_index.adoc:60 #, no-wrap msgid "Default Shell" msgstr "Стандартная оболочка" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:68 msgid "" "Linux(R) users are often surprised to find that Bash is not the default " "shell in FreeBSD. In fact, Bash is not included in the default " -"installation. Instead, the Bourne shell-compatible man:sh[1] as the default " +"installation. Instead, the POSIX(R)-compatible man:sh[1] is the default " "user shell. The root shell is man:tcsh[1] by default on FreeBSD 13 and " "earlier and man:sh[1] on FreeBSD 14 and later. man:sh[1] is very similar to " "Bash but with a much smaller feature-set. Generally shell scripts written " "for man:sh[1] will run in Bash, but the reverse is not always true." msgstr "" "Пользователи Linux(R) часто удивляются, обнаружив, что Bash не является " "оболочкой по умолчанию в FreeBSD. На самом деле, Bash не включён в " -"стандартную установку. Вместо этого используется совместимая с Bourne shell " -"оболочка man:sh[1] в качестве оболочки пользователя по умолчанию. Оболочка " -"root — это man:tcsh[1] по умолчанию в FreeBSD 13 и более ранних версиях и " -"man:sh[1] в FreeBSD 14 и позднее. Оболочка man:sh[1] очень похожа на Bash, " -"но имеет гораздо меньший набор возможностей. Как правило, скрипты, " +"стандартную установку. Вместо этого используется совместимая с POSIX(R) " +"shell оболочка man:sh[1] в качестве оболочки пользователя по умолчанию. " +"Оболочка root — это man:tcsh[1] по умолчанию в FreeBSD 13 и более ранних " +"версиях и man:sh[1] в FreeBSD 14 и позднее. Оболочка man:sh[1] очень похожа " +"на Bash, но имеет гораздо меньший набор возможностей. Как правило, скрипты, " "написанные для man:sh[1], будут работать в Bash, но обратное не всегда верно." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:70 msgid "" "However, Bash and other shells are available for installation using the " "FreeBSD extref:{handbook}ports[Packages and Ports Collection, ports]." msgstr "" -"Однако Bash и другие оболочки доступны для установки через " -"extref:{handbook}ports[Коллекцию портов и пакетов FreeBSD, ports]." +"Однако Bash и другие оболочки доступны для установки через extref:{handbook}" +"ports[Коллекцию портов и пакетов FreeBSD, ports]." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:75 msgid "" "After installing another shell, use man:chsh[1] to change a user's default " "shell. It is recommended that the `root` user's default shell remain " "unchanged since shells which are not included in the base distribution are " "installed to [.filename]#/usr/local/bin#. In the event of a problem, the " "file system where [.filename]#/usr/local/bin# is located may not be " "mounted. In this case, `root` would not have access to its default shell, " "preventing `root` from logging in and fixing the problem." msgstr "" "После установки другой оболочки используйте man:chsh[1], чтобы изменить " "оболочку пользователя по умолчанию. Рекомендуется оставить оболочку " "пользователя `root` без изменений, поскольку оболочки, не входящие в базовую " "поставку, устанавливаются в [.filename]#/usr/local/bin#. В случае " "возникновения проблемы файловая система, в которой находится [.filename]#/" "usr/local/bin#, может быть не смонтирована. В такой ситуации у `root` не " "будет доступа к своей оболочке по умолчанию, что помешает ему войти в " "систему и устранить проблему." #. type: Title == #: documentation/content/en/articles/linux-users/_index.adoc:77 #, no-wrap msgid "Packages and Ports: Adding Software in FreeBSD" msgstr "Пакеты и порты: установка программ в FreeBSD" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:81 msgid "" "FreeBSD provides two methods for installing applications: binary packages " "and compiled ports. Each method has its own benefits:" msgstr "" "FreeBSD предоставляет два метода установки приложений: бинарные пакеты и " "скомпилированные порты. Каждый метод имеет свои преимущества:" #. type: Block title #: documentation/content/en/articles/linux-users/_index.adoc:82 #, no-wrap msgid "Binary Packages" msgstr "Бинарные пакеты" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:84 msgid "Faster installation as compared to compiling large applications." msgstr "Быстрая установка по сравнению с компиляцией крупных приложений." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:85 msgid "Does not require an understanding of how to compile software." msgstr "Не требует понимания того, как компилировать программное обеспечение." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:86 msgid "No need to install a compiler." msgstr "Нет необходимости устанавливать компилятор." #. type: Title === #: documentation/content/en/articles/linux-users/_index.adoc:87 #: documentation/content/en/articles/linux-users/_index.adoc:112 #, no-wrap msgid "Ports" msgstr "Порты" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:89 msgid "Ability to customize installation options." msgstr "Возможность настройки параметров установки." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:90 msgid "Custom patches can be applied." msgstr "Могут быть применены пользовательские патчи." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:94 msgid "" "If an application installation does not require any customization, " "installing the package is sufficient. Compile the port instead whenever an " "application requires customization of the default options. If needed, a " "custom package can be compiled from ports using `make package`." msgstr "" "Если установка приложения не требует дополнительной собственной настройки, " "достаточно установить пакет. Собирайте порт, если приложению требуется " "изменение параметров, заданных в пакетах по умолчанию. При необходимости " "собственный пакет можно собрать из портов с помощью `make package`." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:96 msgid "" "A complete list of all available ports and packages can be found https://" "ports.freebsd.org[here]." msgstr "" "Полный список всех доступных портов и пакетов можно найти https://ports." "freebsd.org[здесь]." #. type: Title === #: documentation/content/en/articles/linux-users/_index.adoc:98 #, no-wrap msgid "Packages" msgstr "Пакеты" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:103 msgid "" "Packages are pre-compiled applications, the FreeBSD equivalents of [." "filename]#.deb# files on Debian/Ubuntu based systems and [.filename]#.rpm# " "files on Red Hat/Fedora based systems. Packages are installed using `pkg`. " "For example, the following command installs Apache 2.4:" msgstr "" "Пакеты — это предварительно скомпилированные приложения, эквиваленты файлов " "[.filename]#.deb# в системах на основе Debian/Ubuntu и файлов [.filename]#." "rpm# в системах на основе Red Hat/Fedora. Пакеты устанавливаются с помощью " "`pkg`. Например, следующая команда устанавливает Apache 2.4:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-users/_index.adoc:107 #, no-wrap msgid "# pkg install apache24\n" msgstr "# pkg install apache24\n" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:110 msgid "" "For more information on packages refer to section 4.4 of the FreeBSD " "Handbook: extref:{handbook}ports[Using pkgng for Binary Package Management, " "pkgng-intro]." msgstr "" "Для получения дополнительной информации о пакетах обратитесь к разделу 4.4 " "Руководства FreeBSD: extref:{handbook}ports[Использование pkg для управления " "бинарными пакетами, pkgng-intro]." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:116 msgid "" "The FreeBSD Ports Collection is a framework of [.filename]#Makefiles# and " "patches specifically customized for installing applications from source on " "FreeBSD. When installing a port, the system will fetch the source code, " "apply any required patches, compile the code, and install the application " "and any required dependencies." msgstr "" "Коллекция портов FreeBSD — это набор [.filename]#Makefile# и патчей, " "специально адаптированных для установки приложений из исходного кода в " "FreeBSD. При установке порта система загрузит исходный код, применит " "необходимые патчи, скомпилирует код и установит приложение вместе с " "требуемыми зависимостями." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:119 msgid "" "The Ports Collection, sometimes referred to as the ports tree, can be " "installed to [.filename]#/usr/ports# using link:{handbook}mirrors/" "#git[Git]. Detailed instructions for installing the Ports Collection can be " "found in extref:{handbook}ports[section 4.5.1, ports-using-installation-" "methods] of the FreeBSD Handbook." msgstr "" "Коллекция портов, иногда называемая деревом портов, может быть установлена в " "[.filename]#/usr/ports# с помощью link:{handbook}mirrors/#git[Git]. " -"Подробные инструкции по установке Коллекции портов можно найти в " -"extref:{handbook}ports[разделе 4.5.1, ports-using-installation-methods] " -"Руководства FreeBSD." +"Подробные инструкции по установке Коллекции портов можно найти в extref:" +"{handbook}ports[разделе 4.5.1, ports-using-installation-methods] Руководства " +"FreeBSD." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:121 msgid "" "To compile a port, change to the port's directory and start the build " "process. The following example installs Apache 2.4 from the Ports Collection:" msgstr "" "Для сборки порта перейдите в его каталог и запустите процесс сборки. В " "следующем примере устанавливается Apache 2.4 из коллекции портов:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-users/_index.adoc:126 #, no-wrap msgid "" "# cd /usr/ports/www/apache24\n" "# make install clean\n" msgstr "" "# cd /usr/ports/www/apache24\n" "# make install clean\n" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:130 msgid "" "A benefit of using ports to install software is the ability to customize the " "installation options. This example specifies that the mod_ldap module " "should also be installed:" msgstr "" "Преимущество использования портов для установки программного обеспечения " "заключается в возможности настройки параметров установки. В этом примере " "указано, что также должен быть установлен модуль mod_ldap:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-users/_index.adoc:135 #, no-wrap msgid "" "# cd /usr/ports/www/apache24\n" "# make WITH_LDAP=\"YES\" install clean\n" msgstr "" "# cd /usr/ports/www/apache24\n" "# make WITH_LDAP=\"YES\" install clean\n" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:138 msgid "" "Refer to extref:{handbook}ports[Using the Ports Collection, ports-using] for " "more information." msgstr "" "Обратитесь к разделу extref:{handbook}ports[Использование коллекции портов, " "ports-using] для получения дополнительной информации." #. type: Title == #: documentation/content/en/articles/linux-users/_index.adoc:140 #, no-wrap msgid "System Startup" msgstr "Загрузка системы" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:147 msgid "" "Many Linux(R) distributions use the SysV init system, whereas FreeBSD uses " "the traditional BSD-style man:init[8]. Under the BSD-style man:init[8], " "there are no run-levels and [.filename]#/etc/inittab# does not exist. " "Instead, startup is controlled by man:rc[8] scripts. At system boot, [." "filename]#/etc/rc# reads [.filename]#/etc/rc.conf# and [.filename]#/etc/" "defaults/rc.conf# to determine which services are to be started. The " "specified services are then started by running the corresponding service " "initialization scripts located in [.filename]#/etc/rc.d/# and [.filename]#/" "usr/local/etc/rc.d/#. These scripts are similar to the scripts located in [." "filename]#/etc/init.d/# on Linux(R) systems." msgstr "" "Многие дистрибутивы Linux(R) используют систему инициализации SysV, тогда " "как FreeBSD использует традиционный BSD-стиль man:init[8]. В BSD-стиле man:" "init[8] нет уровней запуска (run-levels), и файл [.filename]#/etc/inittab# " "отсутствует. Вместо этого запуск системы управляется сценариями man:rc[8]. " "При загрузке системы [.filename]#/etc/rc# читает [.filename]#/etc/rc.conf# и " "[.filename]#/etc/defaults/rc.conf#, чтобы определить, какие службы должны " "быть запущены. Указанные службы затем запускаются путем выполнения " "соответствующих сценариев инициализации, расположенных в [.filename]#/etc/rc." "d/# и [.filename]#/usr/local/etc/rc.d/#. Эти сценарии аналогичны сценариям, " "расположенным в [.filename]#/etc/init.d/# в системах Linux(R)." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:150 msgid "" "The scripts found in [.filename]#/etc/rc.d/# are for applications that are " "part of the \"base\" system, such as man:cron[8], man:sshd[8], and man:" "syslog[3]. The scripts in [.filename]#/usr/local/etc/rc.d/# are for user-" "installed applications such as Apache and Squid." msgstr "" "Скрипты, расположенные в [.filename]#/etc/rc.d/#, предназначены для " "приложений, входящих в \"базовую\" систему, таких как man:cron[8], man:" "sshd[8] и man:syslog[3]. Скрипты в [.filename]#/usr/local/etc/rc.d/# " "предназначены для пользовательских приложений, таких как Apache и Squid." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:155 msgid "" "Since FreeBSD is developed as a complete operating system, user-installed " "applications are not considered to be part of the \"base\" system. User-" "installed applications are generally installed using extref:{handbook}" "ports[Packages or Ports, ports-using]. In order to keep them separate from " "the base system, user-installed applications are installed under [." "filename]#/usr/local/#. Therefore, user-installed binaries reside in [." "filename]#/usr/local/bin/#, configuration files are in [.filename]#/usr/" "local/etc/#, and so on." msgstr "" "Поскольку FreeBSD разрабатывается как полноценная операционная система, " "пользовательские приложения не считаются частью «базовой» системы. " -"Пользовательские приложения обычно устанавливаются с помощью " -"extref:{handbook}ports[Пакетов или Портов, ports-using]. Чтобы отделить их " -"от базовой системы, пользовательские приложения устанавливаются в [." -"filename]#/usr/local/#. Таким образом, исполняемые файлы пользовательских " -"приложений находятся в [.filename]#/usr/local/bin/#, конфигурационные файлы —" -" в [.filename]#/usr/local/etc/# и так далее." +"Пользовательские приложения обычно устанавливаются с помощью extref:" +"{handbook}ports[Пакетов или Портов, ports-using]. Чтобы отделить их от " +"базовой системы, пользовательские приложения устанавливаются в [.filename]#/" +"usr/local/#. Таким образом, исполняемые файлы пользовательских приложений " +"находятся в [.filename]#/usr/local/bin/#, конфигурационные файлы — в [." +"filename]#/usr/local/etc/# и так далее." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:160 msgid "" "Services are enabled by adding an entry for the service in [.filename]#/etc/" "rc.conf#. The system defaults are found in [.filename]#/etc/defaults/rc." "conf# and these default settings are overridden by settings in [.filename]#/" "etc/rc.conf#. Refer to man:rc.conf[5] for more information about the " "available entries. When installing additional applications, review the " "application's install message to determine how to enable any associated " "services." msgstr "" "Сервисы включаются путем добавления соответствующей записи в файл [." "filename]#/etc/rc.conf#. Системные параметры по умолчанию находятся в файле " "[.filename]#/etc/defaults/rc.conf#, а настройки по умолчанию " "переопределяются параметрами из файла [.filename]#/etc/rc.conf#. Подробнее о " "доступных параметрах можно узнать в man:rc.conf[5]. При установке " "дополнительных приложений ознакомьтесь с сообщением установки, чтобы " "определить, как включить связанные сервисы." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:162 msgid "" "The following entries in [.filename]#/etc/rc.conf# enable man:sshd[8], " "enable Apache 2.4, and specify that Apache should be started with SSL." msgstr "" "Следующие записи в [.filename]#/etc/rc.conf# включают man:sshd[8], " "активируют Apache 2.4 и указывают, что Apache должен запускаться с SSL." #. type: delimited block . 4 #: documentation/content/en/articles/linux-users/_index.adoc:170 #, no-wrap msgid "" "# enable SSHD\n" "sshd_enable=\"YES\"\n" "# enable Apache with SSL\n" "apache24_enable=\"YES\"\n" "apache24_flags=\"-DSSL\"\n" msgstr "" "# enable SSHD\n" "sshd_enable=\"YES\"\n" "# enable Apache with SSL\n" "apache24_enable=\"YES\"\n" "apache24_flags=\"-DSSL\"\n" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:173 msgid "" "Once a service has been enabled in [.filename]#/etc/rc.conf#, it can be " "started without rebooting the system:" msgstr "" "После включения службы в [.filename]#/etc/rc.conf# её можно запустить без " "перезагрузки системы:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-users/_index.adoc:178 #, no-wrap msgid "" "# service sshd start\n" "# service apache24 start\n" msgstr "" "# service sshd start\n" "# service apache24 start\n" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:181 msgid "" "If a service has not been enabled, it can be started from the command line " "using `onestart`:" msgstr "" "Если служба не была включена, её можно запустить из командной строки с " "помощью `onestart`:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-users/_index.adoc:185 #, no-wrap msgid "# service sshd onestart\n" msgstr "# service sshd onestart\n" #. type: Title == #: documentation/content/en/articles/linux-users/_index.adoc:188 #, no-wrap msgid "Network Configuration" msgstr "Настройка сети" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:192 msgid "" "Instead of a generic _ethX_ identifier that Linux(R) uses to identify a " "network interface, FreeBSD uses the driver name followed by a number. The " "following output from man:ifconfig[8] shows two Intel(R) Pro 1000 network " "interfaces ([.filename]#em0# and [.filename]#em1#):" msgstr "" "Вместо общего идентификатора _ethX_, который используется в Linux(R) для " "обозначения сетевого интерфейса, FreeBSD использует имя драйвера с " "последующим числом. Следующий вывод из man:ifconfig[8] показывает два " "сетевых интерфейса Intel(R) Pro 1000 ([.filename]#em0# и [.filename]#em1#):" #. type: delimited block . 4 #: documentation/content/en/articles/linux-users/_index.adoc:208 #, no-wrap msgid "" "% ifconfig\n" "em0: flags=8843 mtu 1500\n" " options=b\n" " inet 10.10.10.100 netmask 0xffffff00 broadcast 10.10.10.255\n" " ether 00:50:56:a7:70:b2\n" " media: Ethernet autoselect (1000baseTX )\n" " status: active\n" "em1: flags=8843 mtu 1500\n" " options=b\n" " inet 192.168.10.222 netmask 0xffffff00 broadcast 192.168.10.255\n" " ether 00:50:56:a7:03:2b\n" " media: Ethernet autoselect (1000baseTX )\n" " status: active\n" msgstr "" "% ifconfig\n" "em0: flags=8843 mtu 1500\n" " options=b\n" " inet 10.10.10.100 netmask 0xffffff00 broadcast 10.10.10.255\n" " ether 00:50:56:a7:70:b2\n" " media: Ethernet autoselect (1000baseTX )\n" " status: active\n" "em1: flags=8843 mtu 1500\n" " options=b\n" " inet 192.168.10.222 netmask 0xffffff00 broadcast 192.168.10.255\n" " ether 00:50:56:a7:03:2b\n" " media: Ethernet autoselect (1000baseTX )\n" " status: active\n" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:213 msgid "" "An IP address can be assigned to an interface using man:ifconfig[8]. To " "remain persistent across reboots, the IP configuration must be included in [." "filename]#/etc/rc.conf#. The following [.filename]#/etc/rc.conf# entries " "specify the hostname, IP address, and default gateway:" msgstr "" "IP-адрес может быть назначен интерфейсу с помощью man:ifconfig[8]. Чтобы " "настройки сохранялись после перезагрузки, конфигурация IP должна быть " "указана в [.filename]#/etc/rc.conf#. Следующие записи в [.filename]#/etc/rc." "conf# задают имя хоста, IP-адрес и шлюз по умолчанию:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-users/_index.adoc:219 #, no-wrap msgid "" "hostname=\"server1.example.com\"\n" "ifconfig_em0=\"inet 10.10.10.100 netmask 255.255.255.0\"\n" "defaultrouter=\"10.10.10.1\"\n" msgstr "" "hostname=\"server1.example.com\"\n" "ifconfig_em0=\"inet 10.10.10.100 netmask 255.255.255.0\"\n" "defaultrouter=\"10.10.10.1\"\n" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:222 msgid "Use the following entries to instead configure an interface for DHCP:" msgstr "Используйте следующие записи для настройки интерфейса через DHCP:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-users/_index.adoc:227 #, no-wrap msgid "" "hostname=\"server1.example.com\"\n" "ifconfig_em0=\"DHCP\"\n" msgstr "" "hostname=\"server1.example.com\"\n" "ifconfig_em0=\"DHCP\"\n" #. type: Title == #: documentation/content/en/articles/linux-users/_index.adoc:230 #, no-wrap msgid "Firewall" msgstr "Firewall" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:234 msgid "" "FreeBSD does not use Linux(R) IPTABLES for its firewall. Instead, FreeBSD " "offers a choice of three kernel level firewalls:" msgstr "" "FreeBSD не использует Linux(R) IPTABLES для своего межсетевого экрана. " "Вместо этого FreeBSD предлагает выбор из трёх межсетевых экранов на уровне " "ядра:" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:236 msgid "extref:{handbook}firewalls[PF, firewalls-pf]" msgstr "extref:{handbook}firewalls[PF, firewalls-pf]" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:237 msgid "extref:{handbook}firewalls[IPFILTER, firewalls-ipf]" msgstr "extref:{handbook}firewalls[IPFILTER, firewalls-ipf]" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:238 msgid "extref:{handbook}firewalls[IPFW, firewalls-ipfw]" msgstr "extref:{handbook}firewalls[IPFW, firewalls-ipfw]" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:242 msgid "" "PF is developed by the OpenBSD project and ported to FreeBSD. PF was " "created as a replacement for IPFILTER and its syntax is similar to that of " "IPFILTER. PF can be paired with man:altq[4] to provide QoS features." msgstr "" "PF разработан проектом OpenBSD и портирован в FreeBSD. PF был создан как " "замена для IPFILTER, и его синтаксис схож с синтаксисом IPFILTER. PF может " "использоваться совместно с man:altq[4] для обеспечения функций QoS." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:244 msgid "This sample PF entry allows inbound SSH:" msgstr "Этот пример записи PF разрешает входящий SSH:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-users/_index.adoc:248 #, no-wrap msgid "pass in on $ext_if inet proto tcp from any to ($ext_if) port 22\n" msgstr "pass in on $ext_if inet proto tcp from any to ($ext_if) port 22\n" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:252 msgid "" "IPFILTER is the firewall application developed by Darren Reed. It is not " "specific to FreeBSD and has been ported to several operating systems " "including NetBSD, OpenBSD, SunOS, HP/UX, and Solaris." msgstr "" "IPFILTER — это приложение для межсетевого экрана, разработанное Дарреном " "Ридом. Оно не является специфичным для FreeBSD и было портировано на " "несколько операционных систем, включая NetBSD, OpenBSD, SunOS, HP/UX и " "Solaris." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:254 msgid "The IPFILTER syntax to allow inbound SSH is:" msgstr "Синтаксис IPFILTER для разрешения входящего SSH:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-users/_index.adoc:258 #, no-wrap msgid "pass in on $ext_if proto tcp from any to any port = 22\n" msgstr "pass in on $ext_if proto tcp from any to any port = 22\n" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:262 msgid "" "IPFW is the firewall developed and maintained by FreeBSD. It can be paired " "with man:dummynet[4] to provide traffic shaping capabilities and simulate " "different types of network connections." msgstr "" "IPFW — это межсетевой экран, разработанный и поддерживаемый FreeBSD. Он " "может быть использован совместно с man:dummynet[4] для обеспечения " "возможностей управления трафиком и имитации различных типов сетевых " "соединений." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:264 msgid "The IPFW syntax to allow inbound SSH would be:" msgstr "Синтаксис IPFW для разрешения входящего SSH будет следующим:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-users/_index.adoc:268 #, no-wrap msgid "ipfw add allow tcp from any to me 22 in via $ext_if\n" msgstr "ipfw add allow tcp from any to me 22 in via $ext_if\n" #. type: Title == #: documentation/content/en/articles/linux-users/_index.adoc:271 #, no-wrap msgid "Updating FreeBSD" msgstr "Обновление FreeBSD" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:274 msgid "" "There are two methods for updating a FreeBSD system: from source or binary " "updates." msgstr "" "Существует два метода обновления системы FreeBSD: из исходного кода или " "бинарные обновления." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:278 msgid "" "Updating from source is the most involved update method, but offers the " "greatest amount of flexibility. The process involves synchronizing a local " "copy of the FreeBSD source code with the FreeBSD Git repository. Once the " "local source code is up-to-date, a new version of the kernel and userland " "can be compiled." msgstr "" "Обновление из исходного кода — это наиболее сложный метод обновления, но он " "предоставляет наибольшую гибкость. Процесс включает синхронизацию локальной " "копии исходного кода FreeBSD с репозиторием FreeBSD Git. После того как " "локальный исходный код обновлён, можно скомпилировать новую версию ядра и " "пользовательского пространства." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:282 msgid "" "Binary updates are similar to using `yum` or `apt-get` to update a Linux(R) " "system. In FreeBSD, man:freebsd-update[8] can be used fetch new binary " "updates and install them. These updates can be scheduled using man:cron[8]." msgstr "" "Двоичные обновления аналогичны использованию `yum` или `apt-get` для " "обновления системы Linux(R). В FreeBSD, man:freebsd-update[8] может быть " "использован для получения и установки новых двоичных обновлений. Эти " "обновления могут быть запланированы с помощью man:cron[8]." #. type: delimited block = 4 #: documentation/content/en/articles/linux-users/_index.adoc:286 msgid "" "When using man:cron[8] to schedule updates, use `freebsd-update cron` in the " "man:crontab[1] to reduce the possibility of a large number of machines all " "pulling updates at the same time:" msgstr "" "При использовании man:cron[8] для планирования обновлений используйте " "`freebsd-update cron` в man:crontab[1], чтобы снизить вероятность " "одновременного скачивания обновлений большим количеством машин:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-users/_index.adoc:290 #, no-wrap msgid "0 3 * * * root /usr/sbin/freebsd-update cron\n" msgstr "0 3 * * * root /usr/sbin/freebsd-update cron\n" #. type: delimited block = 4 #: documentation/content/en/articles/linux-users/_index.adoc:295 msgid "" "For more information on source and binary updates, refer to extref:{handbook}" "cutting-edge[the chapter on updating, updating-upgrading-freebsdupdate] in " "the FreeBSD Handbook." msgstr "" "Для получения дополнительной информации об обновлениях исходного кода и " "бинарных обновлениях обратитесь к extref:{handbook}cutting-edge[главе об " "обновлениях, updating-upgrading-freebsdupdate] в Руководстве FreeBSD." #. type: Title == #: documentation/content/en/articles/linux-users/_index.adoc:297 #, no-wrap msgid "procfs: Gone But Not Forgotten" msgstr "procfs: ушёл, но не забыт" #. type: delimited block = 4 #: documentation/content/en/articles/linux-users/_index.adoc:301 msgid "" "In some Linux(R) distributions, one could look at [.filename]#/proc/sys/net/" "ipv4/ip_forward# to determine if IP forwarding is enabled. In FreeBSD, man:" "sysctl[8] is instead used to view this and other system settings." msgstr "" "В некоторых дистрибутивах Linux(R) можно посмотреть файл [.filename]#/proc/" "sys/net/ipv4/ip_forward#, чтобы определить, включена ли IP-маршрутизация. В " "FreeBSD вместо этого используется man:sysctl[8] для просмотра этого и других " "системных параметров." #. type: delimited block = 4 #: documentation/content/en/articles/linux-users/_index.adoc:303 msgid "" "For example, use the following to determine if IP forwarding is enabled on a " "FreeBSD system:" msgstr "" "Например, используйте следующую команду, чтобы определить, включена ли IP-" "переадресация в системе FreeBSD:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-users/_index.adoc:308 #, no-wrap msgid "" "% sysctl net.inet.ip.forwarding\n" "net.inet.ip.forwarding: 0\n" msgstr "" "% sysctl net.inet.ip.forwarding\n" "net.inet.ip.forwarding: 0\n" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:311 msgid "Use `-a` to list all the system settings:" msgstr "Используйте `-a` для вывода всех системных настроек:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-users/_index.adoc:315 #, no-wrap msgid "% sysctl -a | more\n" msgstr "% sysctl -a | more\n" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:318 msgid "" "If an application requires procfs, add the following entry to [.filename]#/" "etc/fstab#:" msgstr "" "Если приложению требуется procfs, добавьте следующую запись в [.filename]#/" "etc/fstab#:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-users/_index.adoc:322 #, no-wrap msgid "proc /proc procfs rw,noauto 0 0\n" msgstr "proc /proc procfs rw,noauto 0 0\n" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:325 msgid "" "Including `noauto` will prevent [.filename]#/proc# from being automatically " "mounted at boot." msgstr "" "Добавление `noauto` предотвратит автоматическое монтирование [.filename]#/" "proc# при загрузке." #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:327 msgid "To mount the file system without rebooting:" msgstr "Чтобы подключить файловую систему без перезагрузки:" #. type: delimited block . 4 #: documentation/content/en/articles/linux-users/_index.adoc:331 #, no-wrap msgid "# mount /proc\n" msgstr "# mount /proc\n" #. type: Title == #: documentation/content/en/articles/linux-users/_index.adoc:334 #, no-wrap msgid "Common Commands" msgstr "Распространенные команды" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:337 msgid "Some common command equivalents are as follows:" msgstr "Некоторые эквиваленты распространённых команд приведены ниже:" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:342 #, no-wrap msgid "Linux(R) command (Red Hat/Debian)" msgstr "Команда Linux(R) (Red Hat/Debian)" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:343 #, no-wrap msgid "FreeBSD equivalent" msgstr "Эквивалент FreeBSD" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:345 #, no-wrap msgid "Purpose" msgstr "Назначение" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:346 #, no-wrap msgid "`yum install _package_` / `apt-get install _package_`" msgstr "`yum install _package_` / `apt-get install _package_`" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:347 #, no-wrap msgid "`pkg install _package_`" msgstr "`pkg install _package_`" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:349 #, no-wrap msgid "Install package from remote repository" msgstr "Установить пакет из удалённого репозитория" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:350 #, no-wrap msgid "`rpm -ivh _package_` / `dpkg -i _package_`" msgstr "`rpm -ivh _package_` / `dpkg -i _package_`" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:351 #, no-wrap msgid "`pkg add _package_`" msgstr "`pkg add _package_`" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:353 #, no-wrap msgid "Install local package" msgstr "Установить локальный пакет" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:354 #, no-wrap msgid "`rpm -qa` / `dpkg -l`" msgstr "`rpm -qa` / `dpkg -l`" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:355 #, no-wrap msgid "`pkg info`" msgstr "`pkg info`" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:357 #, no-wrap msgid "List installed packages" msgstr "Список установленных пакетов" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:358 #, no-wrap msgid "`lspci`" msgstr "`lspci`" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:359 #, no-wrap msgid "`pciconf`" msgstr "`pciconf`" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:361 #, no-wrap msgid "List PCI devices" msgstr "Перечислить устройства PCI" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:362 #, no-wrap msgid "`lsmod`" msgstr "`lsmod`" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:363 #, no-wrap msgid "`kldstat`" msgstr "`kldstat`" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:365 #, no-wrap msgid "List loaded kernel modules" msgstr "Перечислить загруженные модули ядра" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:366 #, no-wrap msgid "`modprobe`" msgstr "`modprobe`" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:367 #, no-wrap msgid "`kldload` / `kldunload`" msgstr "`kldload` / `kldunload`" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:369 #, no-wrap msgid "Load/Unload kernel modules" msgstr "Загрузка/выгрузка модулей ядра" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:370 #, no-wrap msgid "`strace`" msgstr "`strace`" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:371 #, no-wrap msgid "`truss`" msgstr "`truss`" #. type: Table #: documentation/content/en/articles/linux-users/_index.adoc:372 #, no-wrap msgid "Trace system calls" msgstr "Трассировка системных вызовов" #. type: Title == #: documentation/content/en/articles/linux-users/_index.adoc:375 #, no-wrap msgid "Conclusion" msgstr "Заключение" #. type: Plain text #: documentation/content/en/articles/linux-users/_index.adoc:378 msgid "" "This document has provided an overview of FreeBSD. Refer to the extref:" "{handbook}[FreeBSD Handbook] for more in-depth coverage of these topics as " "well as the many topics not covered by this document." msgstr "" "Этот документ предоставил обзор FreeBSD. Для более детального изучения этих " "тем, а также многих других, не рассмотренных в данном документе, обратитесь " "к extref:{handbook}[Руководству FreeBSD]." diff --git a/documentation/content/ru/articles/nanobsd/_index.adoc b/documentation/content/ru/articles/nanobsd/_index.adoc index c7b00566ef..761fc3ab71 100644 --- a/documentation/content/ru/articles/nanobsd/_index.adoc +++ b/documentation/content/ru/articles/nanobsd/_index.adoc @@ -1,428 +1,428 @@ --- authors: - author: 'Daniel Gerzo' copyright: '2006 The FreeBSD Documentation Project' description: 'Этот документ предоставляет информацию об инструментах NanoBSD, которые могут быть использованы для создания образов системы FreeBSD для встраиваемых приложений, подходящих для использования на USB-накопителе, карте памяти или других носителях данных.' tags: ["nanobsd", "guide", "embedded", "FreeBSD"] title: 'Введение в NanoBSD' trademarks: ["freebsd", "general"] --- = Введение в NanoBSD :doctype: article :toc: macro :toclevels: 1 :icons: font :sectnums: :sectnumlevels: 6 :source-highlighter: rouge :experimental: :images-path: articles/nanobsd/ ifdef::env-beastie[] ifdef::backend-html5[] include::shared/authors.adoc[] include::shared/mirrors.adoc[] include::shared/releases.adoc[] include::shared/attributes/attributes-{{% lang %}}.adoc[] include::shared/{{% lang %}}/teams.adoc[] include::shared/{{% lang %}}/mailing-lists.adoc[] include::shared/{{% lang %}}/urls.adoc[] :imagesdir: ../../../images/{images-path} endif::[] ifdef::backend-pdf,backend-epub3[] include::../../../../shared/asciidoctor.adoc[] endif::[] endif::[] ifndef::env-beastie[] include::../../../../../shared/asciidoctor.adoc[] endif::[] [.abstract-title] Аннотация Этот документ предоставляет информацию об инструментах NanoBSD, которые могут быть использованы для создания образов системы FreeBSD для встраиваемых приложений, подходящих для использования на USB-накопителе, карте памяти или других носителях данных. ''' toc::[] [[intro]] == Введение в NanoBSD -NanoBSD — это инструмент, разработанный {phk} и в настоящее время поддерживаемый {imp}. Он создает образ системы FreeBSD для встраиваемых приложений, подходящий для использования на USB-накопителе, карте памяти или другом носителе данных. +NanoBSD — это инструмент, разработанный {phk} и в настоящее время поддерживаемый {imp}. Он создаёт образ системы FreeBSD для встраиваемых приложений, подходящий для использования на USB-накопителе, карте памяти или другом носителе данных. Он может использоваться для создания специализированных установочных образов, предназначенных для простой установки и обслуживания систем, обычно называемых "компьютерными устройствами". Компьютерные устройства объединяют аппаратное и программное обеспечение в одном продукте, что означает, что все приложения предустановлены. Устройство подключается к существующей сети и может начать работу (почти) сразу. Возможности NanoBSD включают: * Порты и пакеты работают так же, как в FreeBSD — любое приложение может быть установлено и использовано в образе NanoBSD так же, как и в FreeBSD. * Отсутствие недостающей функциональности — если что-то возможно сделать в FreeBSD, то это же можно сделать и в NanoBSD, за исключением случаев, когда определённые функции были явно удалены из образа NanoBSD при его создании. * Всё доступно только для чтения во время работы — можно безопасно выдернуть шнур питания. Нет необходимости запускать man:fsck[8] после нештатного завершения работы системы. * Простота сборки и настройки — используя всего один shell-скрипт и один файл конфигурации, можно создавать уменьшенные и настроенные образы, удовлетворяющие любым произвольным требованиям. [[howto]] == Инструкция по NanoBSD [[design]] === Дизайн NanoBSD После того как образ записан на носитель, можно загрузить NanoBSD. По умолчанию носитель данных разделён на три части: * Два раздела с образами: `code#1` и `code#2`. * Файловый раздел конфигурации, который может быть смонтирован в каталоге [.filename]#/cfg# во время выполнения. Эти разделы обычно монтируются в режиме только для чтения. Каталоги [.filename]#/etc# и [.filename]#/var# являются дисками man:md[4] (malloc). Раздел конфигурации сохраняется в каталоге [.filename]#/cfg#. Он содержит файлы для каталога [.filename]#/etc# и кратковременно монтируется в режиме только для чтения сразу после загрузки системы, поэтому необходимо копировать изменённые файлы из [.filename]#/etc# обратно в каталог [.filename]#/cfg#, если требуется, чтобы изменения сохранялись после перезагрузки системы. .Внесение постоянных изменений в [.filename]#/etc/resolv.conf# [example] ==== [source, shell] .... # vi /etc/resolv.conf [...] # mount /cfg # cp /etc/resolv.conf /cfg # umount /cfg .... ==== [NOTE] ==== Раздел, содержащий [.filename]#/cfg#, должен монтироваться только во время загрузки и при переопределении конфигурационных файлов. Постоянное подключение [.filename]#/cfg# не является хорошей идеей, особенно если Система NanoBSD работает на носителе данных, который может быть повреждён из-за большого количества операций записи в раздел (например, когда синхронизатор файловой системы записывает данные на системные диски). ==== === Создание образа NanoBSD Для сборки NanoBSD необходим исходный код FreeBSD. Чтобы получить исходный код: [source, shell] .... # git clone https://git.FreeBSD.org/src.git /usr/src .... Для более подробной информации выполните шаги, описанные extref:{handbook}cutting-edge#updating-src-obtaining-src[здесь]. Образ NanoBSD создаётся с помощью простого скрипта [.filename]#nanobsd.sh#, который находится в каталоге [.filename]#/usr/src/tools/tools/nanobsd#. Этот скрипт создаёт образ, который можно записать на носитель с помощью утилиты man:dd[1]. Необходимые команды для создания образа NanoBSD: [source, shell] .... # cd /usr/src/tools/tools/nanobsd <.> # sh nanobsd.sh <.> # cd /usr/obj/nanobsd.full <.> # dd if=_.disk.full of=/dev/da0 bs=64k <.> .... <.> Измените текущий каталог на базовый каталог скрипта сборки NanoBSD. <.> Начните процесс сборки. <.> Измените текущий каталог на место, где расположены собранные образы. <.> Установите NanoBSD на носитель данных. ==== Параметры при сборке образа NanoBSD При создании образа NanoBSD можно передать несколько параметров сборки в [.filename]#nanobsd.sh# через командную строку. Эти параметры могут существенно повлиять на процесс сборки. Некоторые параметры предназначены для выдачи информации с большей или меньшей степенью детализации: * `-h`: выводит страницу с краткой справкой. * `-q`: делает вывод менее подробным. * `-v`: делает вывод более подробным. Некоторые другие параметры могут использоваться для ограничения процесса сборки. Иногда нет необходимости пересобирать всё из исходников, особенно если образ уже был собран и внесены лишь небольшие изменения. * `-k`: не собирать ядро. * `-w`: не собирать системное окружение (world). * `-b`: не собирать ни ядро, ни системное окружение. * `-i`: не создавать образ диска. Поскольку файл не будет создан, его нельзя будет записать на носитель с помощью man:dd[1]. * `-f`: не создавать образ диска первого раздела (что полезно для целей обновления). * `-p`: не подготавливать образ. Пропустить выполнение сценариев настройки и ранней настройки для инкрементального улучшения образа из world, ядра или пакетов. * `-n`: добавляет `-DNO_CLEAN` к `buildworld`, `buildkernel`. Кроме того, все файлы, которые уже были собраны в предыдущем запуске, сохраняются. Файл конфигурации можно использовать для настройки множества элементов. Загрузите его с помощью `-c` Последние параметры: * `-K`: не устанавливать ядро. Образ диска без ядра не сможет выполнить нормальную последовательность загрузки. * `-W`: не собирать системное окружение. * `-B`: не инсталлировать ни ядро, ни системное окружение. * `-I`: собрать образ диска из существующей сборки или установки. Не собирать и не устанавливать ядро, системное окружение и файл конфигурации etc, только создать образ диска. ==== Полный процесс сборки образа Полный процесс сборки образа проходит через множество этапов. Точные шаги зависят от выбранных опций при запуске скрипта. При условии, что скрипт запущен без специальных опций, вот что произойдет. . `run_early_customize`: команды, определённые в предоставленном файле конфигурации. . `clean_build`: Просто очищает среду сборки, удаляя ранее созданные файлы. . `make_conf_build`: Собрать make.conf из переменных `CONF_WORLD` и `CONF_BUILD`. . `build_world`: Сборка системы. . `build_kernel`: Собрать файлы ядра. . `clean_world`: Очистить целевой каталог. . `make_conf_install`: Собрать make.conf из переменных `CONF_WORLD` и `CONF_INSTALL`. . `install_world`: Установить все файлы, собранные во время `buildworld`. . `install_etc`: Установить необходимые файлы в каталог [.filename]#/etc#, используя команду `make distribution`. -. `setup_nanobsd_etc`: на этом этапе происходит первая специфичная для NanoBSD настройка. Создается [.filename]#/etc/diskless#, а корневая файловая система определяется как доступная только для чтения. +. `setup_nanobsd_etc`: на этом этапе происходит первая специфичная для NanoBSD настройка. Создаётся [.filename]#/etc/diskless#, а корневая файловая система определяется как доступная только для чтения. . `install_kernel`: устанавливаются файлы ядра и модулей. . `run_customize`: будут вызваны все пользовательские процедуры настройки. . `setup_nanobsd`: создаётся специальная структура конфигурационных каталогов. Каталог [.filename]#/usr/local/etc# перемещается в [.filename]#/etc/local#, а затем создаётся символическая ссылка из [.filename]#/etc/local# обратно в [.filename]#/usr/local/etc#. . `prune_usr`: пустые каталоги в [.filename]#/usr# удаляются. . `run_late_customize`: на этом этапе могут быть выполнены самые последние пользовательские скрипты. . `fixup_before_diskimage`: Вывести список всех установленных файлов в metalog. -. `create_diskimage`: создает образ диска на основе предоставленных параметров геометрии диска. +. `create_diskimage`: создаёт образ диска на основе предоставленных параметров геометрии диска. . `last_orders`: в настоящее время ничего не делает. === Настройка образа NanoBSD Вероятно, это самая важная и интересная функция NanoBSD. Здесь же вы проведёте большую часть времени при разработке с NanoBSD. Вызов следующей команды заставит [.filename]#nanobsd.sh# прочитать конфигурацию из файла [.filename]#myconf.nano#, расположенного в текущем каталоге: [source, shell] .... # sh nanobsd.sh -c myconf.nano .... Настройка выполняется двумя способами: * Параметры конфигурации * Пользовательские функции ==== Параметры конфигурации С помощью настроек конфигурации можно задать параметры, передаваемые как на этапах `buildworld`, так и `installworld` процесса сборки NanoBSD, а также внутренние параметры, передаваемые основному процессу сборки NanoBSD. Эти параметры позволяют сократить систему так, чтобы она помещалась всего на 64 МБ. Вы можете использовать конфигурационные опции для ещё большего урезания FreeBSD, пока она не будет состоять только из ядра и двух-трёх файлов в пользовательском пространстве. Файл конфигурации состоит из параметров конфигурации, которые переопределяют значения по умолчанию. Наиболее важные директивы: * `NANO_NAME` - Имя сборки (используется для формирования имён рабочих каталогов). * `NANO_SRC` - Путь к исходному дереву, используемому для сборки образа. * `NANO_KERNEL` - Имя файла конфигурации ядра, используемого для сборки ядра. * `CONF_BUILD` - Параметры, передаваемые на этапе `buildworld` сборки. * `CONF_INSTALL` - Параметры, передаваемые на этапе `installworld` при сборке. * `CONF_WORLD` - Параметры, передаваемые на этапах `buildworld` и `installworld` сборки. * `FlashDevice` - Определяет тип носителя для использования. Подробности смотрите в [.filename]#FlashDevice.sub#. Существует множество дополнительных параметров конфигурации, которые могут быть актуальными в зависимости от типа NanoBSD. ===== Общая настройка Существует три этапа, на которых по замыслу можно внести изменения, влияющие на процесс сборки, просто установив переменную в предоставленном конфигурационном файле: * `run_early_customize`: до выполнения любых других действий. * `run_customize`: после размещения всех стандартных файлов. * `run_late_customize`: в самом конце процесса, непосредственно перед созданием фактического образа NanoBSD. Для настройки образа NanoBSD на любом из этих этапов лучше всего добавить конкретное значение в одну из соответствующих переменных. Переменная `NANO_EARLY_CUSTOMIZE` используется на первом этапе процесса сборки. На данный момент нет примера того, что можно сделать с помощью этой переменной, но это может измениться в будущем. Переменная `NANO_CUSTOMIZE` используется после установки ядра, системы и конфигурационных файлов etc, а также настройки файлов etc для установки NanoBSD. Таким образом, это правильный этап процесса сборки для изменения параметров конфигурации и добавления пакетов, как в примере cust_nobeastie. Переменная `NANO_LATE_CUSTOMIZE` используется непосредственно перед созданием образа диска, поэтому это последний момент для внесения изменений. Помните, что процедура `setup_nanobsd` уже выполнена и каталоги [.filename]#etc#, [.filename]#conf# и [.filename]#cfg#, включая подкаталоги, уже изменены, поэтому сейчас не время их корректировать. Вместо этого можно добавить или удалить конкретные файлы. ===== Параметры загрузки Существуют также переменные, которые могут изменить способ загрузки образа NanoBSD. Два параметра передаются в man:boot0cfg[8] для инициализации загрузочного сектора образа диска: * `NANO_BOOT0CFG` * `NANO_BOOTLOADER` С помощью `NANO_BOOTLOADER` можно выбрать файл загрузчика. Наиболее распространённые варианты — [.filename]#boot0sio# и [.filename]#boot0#, в зависимости от наличия последовательного порта у устройства. Лучше не указывать другой загрузчик, но это возможно. Для этого рекомендуется предварительно ознакомиться с extref:{handbook}boot[главой FreeBSD Handbook] о процессе загрузки. С помощью `NANO_BOOT0CFG` можно настроить процесс загрузки, например, выбрать раздел, с которого будет загружаться образ NanoBSD. Перед изменением значения этой переменной рекомендуется ознакомиться со страницей руководства man:boot0cfg[8]. Один из интересных параметров, который можно изменить, — это таймаут процедуры загрузки. Для этого переменную `NANO_BOOT0CFG` можно изменить на `"-o packet -s 1 -m 3 -t 36"`. В этом случае процесс загрузки начнётся примерно через 2 секунды, так как редко возникает необходимость ждать 10 секунд перед началом загрузки. Хорошо знать: переменная `NANO_BOOT2CFG` используется только в подпрограмме `cust_comconsole`, которая может вызываться на этапе `NANO_CUSTOMIZE`, если устройство имеет последовательный порт и весь ввод и вывод консоли должен осуществляться через него. Обязательно проверьте соответствующие параметры последовательного порта, так как установка некорректного значения параметра может сделать его бесполезным. ===== Создание образа диска В конце процесса загрузки происходит создание образа диска. На этом этапе скрипт NanoBSD предоставляет файл, который можно просто скопировать на диск для устройства, и это позволит ему загрузиться и запуститься. Существует множество переменных, которые должны быть настроены правильно, чтобы скрипт создал пригодный для использования образ диска. * Переменная `NANO_DRIVE` должна быть установлена в имя накопителя носителя во время выполнения. Обычно ожидается, что значение по умолчанию `ada0`, которое представляет первое устройство `IDE`/`ATA`/`SATA` на устройстве, будет правильным, но также может использоваться другой тип накопителя — например, USB-ключ, в этом случае это скорее будет `da0`. * Переменная `NANO_MEDIASIZE` должна быть установлена в значение размера (в секторах по 512 байт) носителя данных, который будет использоваться. Если задать её неправильно, образ NanoBSD может вообще не загрузиться, а во время загрузки появится сообщение о некорректной геометрии диска. * Каталоги [.filename]#/etc#, [.filename]#/var# и [.filename]#/tmp# выделяются как диски man:md[4] (malloc) при загрузке; их размеры могут быть настроены в соответствии с потребностями устройства. Переменная `NANO_RAM_ETCSIZE` задаёт размер [.filename]#/etc#, а переменная `NANO_RAM_TMPVARSIZE` определяет размер как [.filename]#/var#, так и [.filename]#/tmp#, поскольку [.filename]#/tmp# символически ссылается на [.filename]#/var/tmp#. По умолчанию размер обоих дисков malloc установлен в 20 МБ каждый. Их можно изменить, но обычно [.filename]#/etc# не сильно увеличивается в размере, поэтому 20 МБ — хорошая начальная точка, тогда как [.filename]#/var# и особенно [.filename]#/tmp# могут стать значительно больше, если не следить за ними. Для систем с ограниченной памятью можно выбрать меньшие размеры файловых систем. * Поскольку NanoBSD в основном предназначен для создания образа системы для устройства, предполагается, что используемые носители данных будут относительно небольшими. По этой причине файловая система настроена на использование небольшого размера блока (4 Кб) и небольшого размера фрагмента (512 байт). Параметры конфигурации файловой системы можно изменить с помощью переменной `NANO_NEWFS`, но синтаксис должен соответствовать формату команды man:newfs[8]. Кроме того, по умолчанию в файловой системе включены Soft Updates. Подробнее об этом можно узнать в extref:{handbook}[FreeBSD Handbook]. * Различные размеры разделов могут быть заданы с использованием `NANO_CODESIZE`, `NANO_CONFSIZE` и `NANO_DATASIZE` в виде кратного 512-байтным секторам. `NANO_CODESIZE` определяет размер первых двух разделов образа: `code#1` и `code#2`. Они должны быть достаточно большими, чтобы вместить все файлы, созданные в результате процессов `buildworld` и `buildkernel`. `NANO_CONFSIZE` определяет размер раздела для конфигурационных файлов, поэтому он не должен быть очень большим; однако не стоит делать его слишком маленьким, чтобы он мог вместить все конфигурационные файлы. Наконец, `NANO_DATASIZE` определяет размер дополнительного раздела, который может использоваться на устройстве. Последний раздел может быть использован, например, для хранения файлов, создаваемых на лету на диске. ==== Пользовательские функции Возможно тонко настроить NanoBSD с помощью функций оболочки в конфигурационном файле. Следующий пример иллюстрирует базовую модель пользовательских функций: [.programlisting] .... cust_foo () ( echo "bar=baz" > \ ${NANO_WORLDDIR}/etc/foo ) customize_cmd cust_foo .... Более полезный пример функции настройки — следующий, который изменяет размер каталога [.filename]#/etc# по умолчанию с 5 МБ на 30 МБ: [.programlisting] .... cust_etc_size () ( cd ${NANO_WORLDDIR}/conf echo 30000 > default/etc/md_size ) customize_cmd cust_etc_size .... Существует несколько предопределённых функций для настройки, готовых к использованию: * `cust_comconsole` - Отключает man:getty[8] на VGA-устройствах (узлы устройств [.filename]#/dev/ttyv*#) и позволяет использовать последовательный порт COM1 в качестве системной консоли. * `cust_allow_ssh_root` - Разрешить `root` входить через man:sshd[8]. * `cust_install_files` - Устанавливает файлы из каталога [.filename]#nanobsd/Files#, который содержит полезные скрипты для администрирования системы. * `cust_pkgng` - Устанавливает пакеты из каталога [.filename]#nanobsd/Pkg# (также требуется пакет pkg-* для начальной загрузки). ==== Добавление пакетов Пакеты могут быть добавлены в образ NanoBSD для обеспечения специфических функциональных возможностей устройства. Для этого можно: * Добавьте `cust_pkgng` в переменную `NANO_CUSTOMIZE` или * Добавьте команду `'customize_cmd cust_pkgng'` в настраиваемый конфигурационный файл. Оба метода приводят к одному результату: запуск процедуры `cust_pkgng`. Эта процедура проверит каталог `NANO_PACKAGE_DIR` для поиска всех пакетов или только списка пакетов, указанных в переменной `NANO_PACKAGE_LIST`. Обычно при установке приложений через pkg в стандартной среде FreeBSD процесс установки размещает конфигурационные файлы в каталоге [.filename]#usr/local/etc#, а скрипты запуска — в каталоге [.filename]#/usr/local/etc/rc.d#. Поэтому после установки необходимых пакетов их нужно настроить, чтобы они запускались сразу после установки. Для этого необходимо разместить соответствующие конфигурационные файлы в правильных каталогах. Это можно сделать, написав специализированные процедуры, или использовать общую процедуру `cust_install_files` для корректного размещения файлов из каталога [.filename]#/usr/src/tools/tools/nanobsd/Files#. Обычно также требуется добавить одну или несколько записей в файл [.filename]#/etc/rc.conf# для каждого пакета. ==== Пример файла конфигурации Полный пример конфигурационного файла для создания пользовательского образа NanoBSD может выглядеть следующим образом: [.programlisting] .... NANO_NAME=custom NANO_SRC=/usr/src NANO_KERNEL=MYKERNEL NANO_IMAGES=2 CONF_BUILD=' WITHOUT_KLDLOAD=YES WITHOUT_NETGRAPH=YES WITHOUT_PAM=YES ' CONF_INSTALL=' WITHOUT_ACPI=YES WITHOUT_BLUETOOTH=YES WITHOUT_FORTRAN=YES WITHOUT_HTML=YES WITHOUT_LPR=YES WITHOUT_MAN=YES WITHOUT_SENDMAIL=YES WITHOUT_SHAREDOCS=YES WITHOUT_EXAMPLES=YES WITHOUT_INSTALLLIB=YES WITHOUT_CALENDAR=YES WITHOUT_MISC=YES WITHOUT_SHARE=YES ' CONF_WORLD=' WITHOUT_BIND=YES WITHOUT_MODULES=YES WITHOUT_KERBEROS=YES WITHOUT_GAMES=YES WITHOUT_RESCUE=YES WITHOUT_LOCALES=YES WITHOUT_SYSCONS=YES WITHOUT_INFO=YES ' FlashDevice SanDisk 1G cust_nobeastie() ( touch ${NANO_WORLDDIR}/boot/loader.conf echo "beastie_disable=\"YES\"" >> ${NANO_WORLDDIR}/boot/loader.conf ) customize_cmd cust_comconsole customize_cmd cust_install_files customize_cmd cust_allow_ssh_root customize_cmd cust_nobeastie .... Все параметры сборки и установки можно найти на странице Справочника man:src.conf[5], но не все параметры можно или следует использовать при создании образа NanoBSD. Параметры сборки и установки должны определяться в соответствии с потребностями создаваемого образа. Например, FTP-клиент и сервер могут не потребоваться. Добавление `WITHOUT_FTP=TRUE` в файл конфигурации в разделе `CONF_BUILD` позволит избежать их сборки. Также, если устройство NanoBSD не будет использоваться для сборки программ, можно добавить `WITHOUT_BINUTILS=TRUE` в раздел `CONF_INSTALL`, но не в раздел `CONF_BUILD`, так как они будут использоваться для сборки образа NanoBSD. Исключение сборки определённого набора программ через параметры компиляции — сокращает общее время сборки и уменьшает требуемый размер дискового образа, тогда как отсутствие установки того же набора программ не сокращает общее время сборки. === Обновление NanoBSD Процесс обновления NanoBSD относительно прост: [.procedure] ==== . Соберите новый образ NanoBSD, как обычно. . Загрузите новый образ в неиспользуемый раздел работающего устройства NanoBSD. + Важнейшее отличие этого шага от первоначальной установки NanoBSD заключается в том, что теперь вместо использования [.filename]#\_.disk.full# (который содержит образ всего диска), устанавливается образ [.filename]#_.disk.image# (который содержит образ одного системного раздела). . Перезагрузите систему и запустите её с только что установленного раздела. . Если все прошло успешно, обновление завершено. . Если что-то пойдет не так, перезагрузитесь обратно в предыдущий раздел (который содержит старую, рабочую версию), чтобы восстановить работоспособность системы как можно быстрее. Исправьте все проблемы новой сборки и повторите процесс. ==== Для установки нового образа на работающую систему NanoBSD можно использовать скрипт [.filename]#updatep1# или [.filename]#updatep2#, расположенный в каталоге [.filename]#/root#, в зависимости от того, с какого раздела запущена текущая система. В зависимости от того, какие службы доступны на хосте, предоставляющем новый образ NanoBSD, и какой тип передачи предпочтителен, можно использовать один из следующих трёх способов: ==== Использование man:ftp[1] Если скорость передачи данных стоит на первом месте, используйте этот пример: [source, shell] .... # ftp myhost get _.disk.image "| sh updatep1" .... ==== Использование man:ssh[1] Если предпочтителен безопасный способ передачи, рассмотрите следующий пример: [source, shell] .... # ssh myhost cat _.disk.image.gz | zcat | sh updatep1 .... ==== Использование man:nc[1] Попробуйте этот пример, если на удалённом хосте не запущены ни служба man:ftpd[8], ни служба man:sshd[8]: [.procedure] ==== . Сначала откройте TCP-слушатель на хосте, обслуживающем образ, и настройте его на отправку образа клиенту: + [source, shell] .... myhost# nc -l 2222 < _.disk.image .... + [NOTE] ====== Убедитесь, что выбранный порт не заблокирован межсетевым экраном для приёма входящих соединений с хоста NanoBSD. ====== . Подключитесь к хосту, предоставляющему новый образ, и выполните скрипт [.filename]#updatep1#: + [source, shell] .... # nc myhost 2222 | sh updatep1 .... ==== diff --git a/documentation/content/ru/articles/nanobsd/_index.po b/documentation/content/ru/articles/nanobsd/_index.po index d037e5aeb9..7b2aaa3dc3 100644 --- a/documentation/content/ru/articles/nanobsd/_index.po +++ b/documentation/content/ru/articles/nanobsd/_index.po @@ -1,1579 +1,1579 @@ # SOME DESCRIPTIVE TITLE # Copyright (C) YEAR The FreeBSD Project # This file is distributed under the same license as the FreeBSD Documentation package. # Vladlen Popolitov , 2025, 2026. msgid "" msgstr "" "Project-Id-Version: FreeBSD Documentation VERSION\n" "POT-Creation-Date: 2026-02-22 15:58+0000\n" -"PO-Revision-Date: 2026-03-04 20:01+0000\n" +"PO-Revision-Date: 2026-04-05 04:45+0000\n" "Last-Translator: Vladlen Popolitov \n" "Language-Team: Russian \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "X-Generator: Weblate 4.17\n" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:1 #: documentation/content/en/articles/nanobsd/_index.adoc:46 #, no-wrap msgid "This document provides information about the NanoBSD tools, which can be used to create FreeBSD system images for embedded applications, suitable for use on a USB key, memory card or other mass storage media." msgstr "Этот документ предоставляет информацию об инструментах NanoBSD, которые могут быть использованы для создания образов системы FreeBSD для встраиваемых приложений, подходящих для использования на USB-накопителе, карте памяти или других носителях данных." #. type: Title == #: documentation/content/en/articles/nanobsd/_index.adoc:1 #: documentation/content/en/articles/nanobsd/_index.adoc:11 #: documentation/content/en/articles/nanobsd/_index.adoc:52 #, no-wrap msgid "Introduction to NanoBSD" msgstr "Введение в NanoBSD" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:44 msgid "Abstract" msgstr "Аннотация" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:48 msgid "'''" msgstr "'''" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:56 msgid "" "NanoBSD is a tool developed by {phk} and now maintained by {imp}. It " "creates a FreeBSD system image for embedded applications, suitable for use " "on a USB key, memory card or other mass storage media." msgstr "" "NanoBSD — это инструмент, разработанный {phk} и в настоящее время " -"поддерживаемый {imp}. Он создает образ системы FreeBSD для встраиваемых " +"поддерживаемый {imp}. Он создаёт образ системы FreeBSD для встраиваемых " "приложений, подходящий для использования на USB-накопителе, карте памяти или " "другом носителе данных." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:60 msgid "" "It can be used to build specialized install images, designed for easy " "installation and maintenance of systems commonly called \"computer appliances" "\". Computer appliances have their hardware and software bundled in the " "product, which means all applications are pre-installed. The appliance is " "plugged into an existing network and can begin working (almost) immediately." msgstr "" "Он может использоваться для создания специализированных установочных " "образов, предназначенных для простой установки и обслуживания систем, обычно " "называемых \"компьютерными устройствами\". Компьютерные устройства " "объединяют аппаратное и программное обеспечение в одном продукте, что " "означает, что все приложения предустановлены. Устройство подключается к " "существующей сети и может начать работу (почти) сразу." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:62 msgid "The features of NanoBSD include:" msgstr "Возможности NanoBSD включают:" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:64 msgid "" "Ports and packages work as in FreeBSD - Every single application can be " "installed and used in a NanoBSD image, the same way as in FreeBSD." msgstr "" "Порты и пакеты работают так же, как в FreeBSD — любое приложение может быть " "установлено и использовано в образе NanoBSD так же, как и в FreeBSD." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:65 msgid "" "No missing functionality - If it is possible to do something with FreeBSD, " "it is possible to do the same thing with NanoBSD, unless the specific " "feature or features were explicitly removed from the NanoBSD image when it " "was created." msgstr "" "Отсутствие недостающей функциональности — если что-то возможно сделать в " "FreeBSD, то это же можно сделать и в NanoBSD, за исключением случаев, когда " "определённые функции были явно удалены из образа NanoBSD при его создании." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:66 msgid "" "Everything is read-only at run-time - It is safe to pull the power-plug. " "There is no necessity to run man:fsck[8] after a non-graceful shutdown of " "the system." msgstr "" "Всё доступно только для чтения во время работы — можно безопасно выдернуть " "шнур питания. Нет необходимости запускать man:fsck[8] после нештатного " "завершения работы системы." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:67 msgid "" "Easy to build and customize - Making use of just one shell script and one " "configuration file it is possible to build reduced and customized images " "satisfying any arbitrary set of requirements." msgstr "" "Простота сборки и настройки — используя всего один shell-скрипт и один файл " "конфигурации, можно создавать уменьшенные и настроенные образы, " "удовлетворяющие любым произвольным требованиям." #. type: Title == #: documentation/content/en/articles/nanobsd/_index.adoc:69 #, no-wrap msgid "NanoBSD Howto" msgstr "Инструкция по NanoBSD" #. type: Title === #: documentation/content/en/articles/nanobsd/_index.adoc:72 #, no-wrap msgid "The Design of NanoBSD" msgstr "Дизайн NanoBSD" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:76 msgid "" "Once the image is present on the medium, it is possible to boot NanoBSD. " "The mass storage medium is divided into three parts by default:" msgstr "" "После того как образ записан на носитель, можно загрузить NanoBSD. По " "умолчанию носитель данных разделён на три части:" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:78 msgid "Two image partitions: `code#1` and `code#2`." msgstr "Два раздела с образами: `code#1` и `code#2`." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:79 msgid "" "The configuration file partition, which can be mounted under the [." "filename]#/cfg# directory at run time." msgstr "" "Файловый раздел конфигурации, который может быть смонтирован в каталоге [." "filename]#/cfg# во время выполнения." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:81 msgid "These partitions are normally mounted read-only." msgstr "Эти разделы обычно монтируются в режиме только для чтения." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:83 msgid "" "The [.filename]#/etc# and [.filename]#/var# directories are man:md[4] " "(malloc) disks." msgstr "" "Каталоги [.filename]#/etc# и [.filename]#/var# являются дисками man:md[4] " "(malloc)." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:86 msgid "" "The configuration file partition persists under the [.filename]#/cfg# " "directory. It contains files for [.filename]#/etc# directory and is briefly " "mounted read-only right after the system boot, therefore it is required to " "copy modified files from [.filename]#/etc# back to the [.filename]#/cfg# " "directory if changes are expected to persist after the system restarts." msgstr "" "Раздел конфигурации сохраняется в каталоге [.filename]#/cfg#. Он содержит " "файлы для каталога [.filename]#/etc# и кратковременно монтируется в режиме " "только для чтения сразу после загрузки системы, поэтому необходимо " "копировать изменённые файлы из [.filename]#/etc# обратно в каталог [." "filename]#/cfg#, если требуется, чтобы изменения сохранялись после " "перезагрузки системы." #. type: Block title #: documentation/content/en/articles/nanobsd/_index.adoc:87 #, no-wrap msgid "Making Persistent Changes to [.filename]#/etc/resolv.conf#" msgstr "Внесение постоянных изменений в [.filename]#/etc/resolv.conf#" #. type: delimited block . 4 #: documentation/content/en/articles/nanobsd/_index.adoc:98 #, no-wrap msgid "" "# vi /etc/resolv.conf\n" "[...]\n" "# mount /cfg\n" "# cp /etc/resolv.conf /cfg\n" "# umount /cfg\n" msgstr "" "# vi /etc/resolv.conf\n" "[...]\n" "# mount /cfg\n" "# cp /etc/resolv.conf /cfg\n" "# umount /cfg\n" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:105 msgid "" "The partition containing [.filename]#/cfg# should be mounted only at boot " "time and while overriding the configuration files." msgstr "" "Раздел, содержащий [.filename]#/cfg#, должен монтироваться только во время " "загрузки и при переопределении конфигурационных файлов." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:107 msgid "" "Keeping [.filename]#/cfg# mounted at all times is not a good idea, " "especially if the NanoBSD system runs off a mass storage medium that may be " "adversely affected by a large number of writes to the partition (like when " "the filesystem syncer flushes data to the system disks)." msgstr "" "Постоянное подключение [.filename]#/cfg# не является хорошей идеей, особенно " "если Система NanoBSD работает на носителе данных, который может быть " "повреждён из-за большого количества операций записи в раздел (например, " "когда синхронизатор файловой системы записывает данные на системные диски)." #. type: Title === #: documentation/content/en/articles/nanobsd/_index.adoc:109 #, no-wrap msgid "Building a NanoBSD Image" msgstr "Создание образа NanoBSD" #. type: delimited block = 4 #: documentation/content/en/articles/nanobsd/_index.adoc:113 msgid "" "The source code of FreeBSD is required to build NanoBSD. To obtain the " "source code:" msgstr "" "Для сборки NanoBSD необходим исходный код FreeBSD. Чтобы получить исходный " "код:" #. type: delimited block . 4 #: documentation/content/en/articles/nanobsd/_index.adoc:117 #, no-wrap msgid "# git clone https://git.FreeBSD.org/src.git /usr/src\n" msgstr "# git clone https://git.FreeBSD.org/src.git /usr/src\n" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:120 msgid "" "For more details, follow the steps extref:{handbook}cutting-edge#updating-" "src-obtaining-src[here]." msgstr "" "Для более подробной информации выполните шаги, описанные extref:{handbook}" "cutting-edge#updating-src-obtaining-src[здесь]." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:123 msgid "" "A NanoBSD image is built using a simple [.filename]#nanobsd.sh# shell " "script, which can be found in the [.filename]#/usr/src/tools/tools/nanobsd# " "directory. This script creates an image, which can be copied on the storage " "medium using the man:dd[1] utility." msgstr "" "Образ NanoBSD создаётся с помощью простого скрипта [.filename]#nanobsd.sh#, " "который находится в каталоге [.filename]#/usr/src/tools/tools/nanobsd#. Этот " "скрипт создаёт образ, который можно записать на носитель с помощью утилиты " "man:dd[1]." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:125 msgid "The necessary commands to build a NanoBSD image are:" msgstr "Необходимые команды для создания образа NanoBSD:" #. type: delimited block . 4 #: documentation/content/en/articles/nanobsd/_index.adoc:132 #, no-wrap msgid "" "# cd /usr/src/tools/tools/nanobsd <.>\n" "# sh nanobsd.sh <.>\n" "# cd /usr/obj/nanobsd.full <.>\n" "# dd if=_.disk.full of=/dev/da0 bs=64k <.>\n" msgstr "" "# cd /usr/src/tools/tools/nanobsd <.>\n" "# sh nanobsd.sh <.>\n" "# cd /usr/obj/nanobsd.full <.>\n" "# dd if=_.disk.full of=/dev/da0 bs=64k <.>\n" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:135 msgid "" "Change the current directory to the base directory of the NanoBSD build " "script." msgstr "Измените текущий каталог на базовый каталог скрипта сборки NanoBSD." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:137 msgid "Start the build process." msgstr "Начните процесс сборки." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:139 msgid "" "Change the current directory to the place where the built images are located." msgstr "Измените текущий каталог на место, где расположены собранные образы." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:141 msgid "Install NanoBSD onto the storage medium." msgstr "Установите NanoBSD на носитель данных." #. type: Title ==== #: documentation/content/en/articles/nanobsd/_index.adoc:142 #, no-wrap msgid "Options When Building a NanoBSD Image" msgstr "Параметры при сборке образа NanoBSD" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:146 msgid "" "When building a NanoBSD image, several build options can be passed to [." "filename]#nanobsd.sh# on the command line. These options can have a " "significant impact on the build process." msgstr "" "При создании образа NanoBSD можно передать несколько параметров сборки в [." "filename]#nanobsd.sh# через командную строку. Эти параметры могут " "существенно повлиять на процесс сборки." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:148 msgid "Some options are for verbosity purposes:" msgstr "" "Некоторые параметры предназначены для выдачи информации с большей или " "меньшей степенью детализации:" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:150 msgid "`-h`: prints the help summary page." msgstr "`-h`: выводит страницу с краткой справкой." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:151 msgid "`-q`: makes output quieter." msgstr "`-q`: делает вывод менее подробным." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:152 msgid "`-v`: makes output more verbose." msgstr "`-v`: делает вывод более подробным." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:155 msgid "" "Some other options can be used to restrict the building process. Sometimes " "it is not necessary to rebuild everything from sources, especially if an " "image has already been built, and only little change is made." msgstr "" "Некоторые другие параметры могут использоваться для ограничения процесса " "сборки. Иногда нет необходимости пересобирать всё из исходников, особенно " "если образ уже был собран и внесены лишь небольшие изменения." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:157 msgid "`-k`: do not build the kernel." msgstr "`-k`: не собирать ядро." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:158 msgid "`-w`: do not build world." msgstr "`-w`: не собирать системное окружение (world)." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:159 msgid "`-b`: do not build either kernel and world." msgstr "`-b`: не собирать ни ядро, ни системное окружение." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:160 msgid "" "`-i`: do not build a disk image at all. As a file will not be created, it " "will not be possible to man:dd[1] it to a storage media." msgstr "" "`-i`: не создавать образ диска. Поскольку файл не будет создан, его нельзя " "будет записать на носитель с помощью man:dd[1]." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:161 msgid "" "`-f`: do not build a disk image of the first partition (which is useful for " "upgrade purposes)." msgstr "" "`-f`: не создавать образ диска первого раздела (что полезно для целей " "обновления)." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:162 msgid "" "`-p`: do not prepare the image. Skip running customization and early-" "customization scripts for incremental image refinement from world, kernel, " "or packages." msgstr "" "`-p`: не подготавливать образ. Пропустить выполнение сценариев настройки и " "ранней настройки для инкрементального улучшения образа из world, ядра или " "пакетов." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:163 msgid "" "`-n`: add `-DNO_CLEAN` to `buildworld`, `buildkernel`. Also, all the files " "that have already been built in a previous run are kept." msgstr "" "`-n`: добавляет `-DNO_CLEAN` к `buildworld`, `buildkernel`. Кроме того, все " "файлы, которые уже были собраны в предыдущем запуске, сохраняются." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:166 msgid "" "A configuration file can be used to tweak as many elements as desired. Load " "it with `-c`" msgstr "" "Файл конфигурации можно использовать для настройки множества элементов. " "Загрузите его с помощью `-c`" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:168 msgid "The last options are:" msgstr "Последние параметры:" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:170 msgid "" "`-K`: do not install a kernel. A disk image without a kernel will not be " "able to achieve a normal boot sequence." msgstr "" "`-K`: не устанавливать ядро. Образ диска без ядра не сможет выполнить " "нормальную последовательность загрузки." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:171 msgid "`-W`: do not install world." msgstr "`-W`: не собирать системное окружение." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:172 msgid "`-B`: do not install either kernel and world." msgstr "`-B`: не инсталлировать ни ядро, ни системное окружение." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:173 msgid "" "`-I`: build a disk image from an existing build or install. Do not build or " "install kernel, world, and the etc configuration file, just create the disk " "image." msgstr "" "`-I`: собрать образ диска из существующей сборки или установки. Не собирать " "и не устанавливать ядро, системное окружение и файл конфигурации etc, только " "создать образ диска." #. type: Title ==== #: documentation/content/en/articles/nanobsd/_index.adoc:174 #, no-wrap msgid "The Complete Image Building Process" msgstr "Полный процесс сборки образа" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:179 msgid "" "The complete image building process is going through a lot of steps. The " "exact steps taken will depend on the chosen options when starting the " "script. Assuming the script is run with no particular options, this is what " "will happen." msgstr "" "Полный процесс сборки образа проходит через множество этапов. Точные шаги " "зависят от выбранных опций при запуске скрипта. При условии, что скрипт " "запущен без специальных опций, вот что произойдет." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:181 msgid "" "`run_early_customize`: Commands that are defined in a supplied configuration " "file." msgstr "" "`run_early_customize`: команды, определённые в предоставленном файле " "конфигурации." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:182 msgid "" "`clean_build`: Just cleans the build environment by deleting the previously " "built files." msgstr "" "`clean_build`: Просто очищает среду сборки, удаляя ранее созданные файлы." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:183 msgid "" "`make_conf_build`: Assemble make.conf from the `CONF_WORLD` and `CONF_BUILD` " "variables." msgstr "" "`make_conf_build`: Собрать make.conf из переменных `CONF_WORLD` и " "`CONF_BUILD`." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:184 msgid "`build_world`: Build world." msgstr "`build_world`: Сборка системы." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:185 msgid "`build_kernel`: Build the kernel files." msgstr "`build_kernel`: Собрать файлы ядра." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:186 msgid "`clean_world`: Clean the destination directory." msgstr "`clean_world`: Очистить целевой каталог." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:187 msgid "" "`make_conf_install`: Assemble make.conf from the `CONF_WORLD` and " "`CONF_INSTALL` variables." msgstr "" "`make_conf_install`: Собрать make.conf из переменных `CONF_WORLD` и " "`CONF_INSTALL`." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:188 msgid "`install_world`: Install all files built during `buildworld`." msgstr "" "`install_world`: Установить все файлы, собранные во время `buildworld`." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:189 msgid "" "`install_etc`: Install the necessary files in the [.filename]#/etc# " "directory, based on the `make distribution` command." msgstr "" "`install_etc`: Установить необходимые файлы в каталог [.filename]#/etc#, " "используя команду `make distribution`." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:190 msgid "" "`setup_nanobsd_etc`: The first configuration specific to NanoBSD takes place " "at this stage. The [.filename]#/etc/diskless# is created and the root " "filesystem is defined as read-only." msgstr "" "`setup_nanobsd_etc`: на этом этапе происходит первая специфичная для NanoBSD " -"настройка. Создается [.filename]#/etc/diskless#, а корневая файловая система " +"настройка. Создаётся [.filename]#/etc/diskless#, а корневая файловая система " "определяется как доступная только для чтения." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:191 msgid "`install_kernel`: The kernel and modules files are installed." msgstr "`install_kernel`: устанавливаются файлы ядра и модулей." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:192 msgid "" "`run_customize`: All the customizing routines defined by the user will be " "called." msgstr "" "`run_customize`: будут вызваны все пользовательские процедуры настройки." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:193 msgid "" "`setup_nanobsd`: A special configuration directory layout is setup. The [." "filename]#/usr/local/etc# gets moved to [.filename]#/etc/local# and a " "symbolic link is created back from [.filename]#/etc/local# to [.filename]#/" "usr/local/etc#." msgstr "" "`setup_nanobsd`: создаётся специальная структура конфигурационных каталогов. " "Каталог [.filename]#/usr/local/etc# перемещается в [.filename]#/etc/local#, " "а затем создаётся символическая ссылка из [.filename]#/etc/local# обратно в [" ".filename]#/usr/local/etc#." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:194 msgid "`prune_usr`: The empty directories from [.filename]#/usr# are removed." msgstr "`prune_usr`: пустые каталоги в [.filename]#/usr# удаляются." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:195 msgid "" "`run_late_customize`: The very last custom scripts can be run at this point." msgstr "" "`run_late_customize`: на этом этапе могут быть выполнены самые последние " "пользовательские скрипты." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:196 msgid "`fixup_before_diskimage`: List all installed files in a metalog." msgstr "" "`fixup_before_diskimage`: Вывести список всех установленных файлов в metalog." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:197 msgid "" "`create_diskimage`: Creates the actual disk image, based on the disk " "geometries provides parameters." msgstr "" -"`create_diskimage`: создает образ диска на основе предоставленных параметров " +"`create_diskimage`: создаёт образ диска на основе предоставленных параметров " "геометрии диска." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:198 msgid "`last_orders`: Does nothing for now." msgstr "`last_orders`: в настоящее время ничего не делает." #. type: Title === #: documentation/content/en/articles/nanobsd/_index.adoc:199 #, no-wrap msgid "Customizing a NanoBSD Image" msgstr "Настройка образа NanoBSD" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:203 msgid "" "This is probably the most important and most interesting feature of " "NanoBSD. This is also where you will be spending most of the time when " "developing with NanoBSD." msgstr "" "Вероятно, это самая важная и интересная функция NanoBSD. Здесь же вы " "проведёте большую часть времени при разработке с NanoBSD." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:205 msgid "" "Invocation of the following command will force the [.filename]#nanobsd.sh# " "to read its configuration from [.filename]#myconf.nano# located in the " "current directory:" msgstr "" "Вызов следующей команды заставит [.filename]#nanobsd.sh# прочитать " "конфигурацию из файла [.filename]#myconf.nano#, расположенного в текущем " "каталоге:" #. type: delimited block . 4 #: documentation/content/en/articles/nanobsd/_index.adoc:209 #, no-wrap msgid "# sh nanobsd.sh -c myconf.nano\n" msgstr "# sh nanobsd.sh -c myconf.nano\n" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:212 msgid "Customization is done in two ways:" msgstr "Настройка выполняется двумя способами:" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:214 msgid "Configuration options" msgstr "Параметры конфигурации" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:215 msgid "Custom functions" msgstr "Пользовательские функции" #. type: Title ==== #: documentation/content/en/articles/nanobsd/_index.adoc:216 #, no-wrap msgid "Configuration Options" msgstr "Параметры конфигурации" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:221 msgid "" "With configuration settings, it is possible to configure options passed to " "both the `buildworld` and `installworld` stages of the NanoBSD build " "process, as well as internal options passed to the main build process of " "NanoBSD. Through these options it is possible to cut the system down, so it " "will fit on as little as 64MB. You can use the configuration options to " "trim down FreeBSD even more, until it will consists of just the kernel and " "two or three files in the userland." msgstr "" "С помощью настроек конфигурации можно задать параметры, передаваемые как на " "этапах `buildworld`, так и `installworld` процесса сборки NanoBSD, а также " "внутренние параметры, передаваемые основному процессу сборки NanoBSD. Эти " "параметры позволяют сократить систему так, чтобы она помещалась всего на 64 " "МБ. Вы можете использовать конфигурационные опции для ещё большего урезания " "FreeBSD, пока она не будет состоять только из ядра и двух-трёх файлов в " "пользовательском пространстве." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:224 msgid "" "The configuration file consists of configuration options, which override the " "default values. The most important directives are:" msgstr "" "Файл конфигурации состоит из параметров конфигурации, которые переопределяют " "значения по умолчанию. Наиболее важные директивы:" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:226 msgid "`NANO_NAME` - Name of build (used to construct the workdir names)." msgstr "" "`NANO_NAME` - Имя сборки (используется для формирования имён рабочих " "каталогов)." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:227 msgid "`NANO_SRC` - Path to the source tree used to build the image." msgstr "`NANO_SRC` - Путь к исходному дереву, используемому для сборки образа." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:228 msgid "`NANO_KERNEL` - Name of kernel configuration file used to build kernel." msgstr "" "`NANO_KERNEL` - Имя файла конфигурации ядра, используемого для сборки ядра." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:229 msgid "`CONF_BUILD` - Options passed to the `buildworld` stage of the build." msgstr "`CONF_BUILD` - Параметры, передаваемые на этапе `buildworld` сборки." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:230 msgid "" "`CONF_INSTALL` - Options passed to the `installworld` stage of the build." msgstr "" "`CONF_INSTALL` - Параметры, передаваемые на этапе `installworld` при сборке." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:231 msgid "" "`CONF_WORLD` - Options passed to both the `buildworld` and the " "`installworld` stage of the build." msgstr "" "`CONF_WORLD` - Параметры, передаваемые на этапах `buildworld` и " "`installworld` сборки." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:232 msgid "" "`FlashDevice` - Defines what type of media to use. Check [." "filename]#FlashDevice.sub# for more details." msgstr "" "`FlashDevice` - Определяет тип носителя для использования. Подробности " "смотрите в [.filename]#FlashDevice.sub#." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:234 msgid "" "There are many more configuration options that could be relevant depending " "upon the kind of NanoBSD that is desired." msgstr "" "Существует множество дополнительных параметров конфигурации, которые могут " "быть актуальными в зависимости от типа NanoBSD." #. type: Title ===== #: documentation/content/en/articles/nanobsd/_index.adoc:235 #, no-wrap msgid "General Customization" msgstr "Общая настройка" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:238 msgid "" "There are three stages, by design, at which it is possible to make changes " "that affect the building process, just by setting up a variable in the " "provided configuration file:" msgstr "" "Существует три этапа, на которых по замыслу можно внести изменения, влияющие " "на процесс сборки, просто установив переменную в предоставленном " "конфигурационном файле:" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:240 msgid "`run_early_customize`: before anything else happens." msgstr "`run_early_customize`: до выполнения любых других действий." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:241 msgid "`run_customize`: after all the standard files have been laid out." msgstr "`run_customize`: после размещения всех стандартных файлов." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:242 msgid "" "`run_late_customize`: at the very end of the process, just before the actual " "NanoBSD image is built." msgstr "" "`run_late_customize`: в самом конце процесса, непосредственно перед " "созданием фактического образа NanoBSD." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:244 msgid "" "To customize a NanoBSD image, at any of these steps, it is best to add a " "specific value to one of the corresponding variables." msgstr "" "Для настройки образа NanoBSD на любом из этих этапов лучше всего добавить " "конкретное значение в одну из соответствующих переменных." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:247 msgid "" "The `NANO_EARLY_CUSTOMIZE` variable is used at the first step of the " "building process. At this point, there is no example as to what can be done " "using that variable, but it may change in the future." msgstr "" "Переменная `NANO_EARLY_CUSTOMIZE` используется на первом этапе процесса " "сборки. На данный момент нет примера того, что можно сделать с помощью этой " "переменной, но это может измениться в будущем." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:250 msgid "" "The `NANO_CUSTOMIZE` variable is used after the kernel, world and etc " "configuration files have been installed, and the etc files have been setup " "as to be a NanoBSD installation. So it is the correct step in the building " "process to tweak configuration options and add packages, like in the " "cust_nobeastie example." msgstr "" "Переменная `NANO_CUSTOMIZE` используется после установки ядра, системы и " "конфигурационных файлов etc, а также настройки файлов etc для установки " "NanoBSD. Таким образом, это правильный этап процесса сборки для изменения " "параметров конфигурации и добавления пакетов, как в примере cust_nobeastie." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:254 msgid "" "The `NANO_LATE_CUSTOMIZE` variable is used just before the disk image is " "created, so it is the very last moment to change anything. Remember that " "the `setup_nanobsd` routine already executed and that the [.filename]#etc#, " "[.filename]#conf# and [.filename]#cfg# directories and subdirectories are " "already modified, so it is not time to change them at this point. Rather, " "it is possible to add or remove specific files." msgstr "" "Переменная `NANO_LATE_CUSTOMIZE` используется непосредственно перед " "созданием образа диска, поэтому это последний момент для внесения изменений. " "Помните, что процедура `setup_nanobsd` уже выполнена и каталоги [." "filename]#etc#, [.filename]#conf# и [.filename]#cfg#, включая подкаталоги, " "уже изменены, поэтому сейчас не время их корректировать. Вместо этого можно " "добавить или удалить конкретные файлы." #. type: Title ===== #: documentation/content/en/articles/nanobsd/_index.adoc:255 #, no-wrap msgid "Booting Options" msgstr "Параметры загрузки" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:259 msgid "" "There are also variables that can change the way the NanoBSD image boots. " "Two options are passed to man:boot0cfg[8] to initialize the boot sector of " "the disk image:" msgstr "" "Существуют также переменные, которые могут изменить способ загрузки образа " "NanoBSD. Два параметра передаются в man:boot0cfg[8] для инициализации " "загрузочного сектора образа диска:" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:261 msgid "`NANO_BOOT0CFG`" msgstr "`NANO_BOOT0CFG`" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:262 msgid "`NANO_BOOTLOADER`" msgstr "`NANO_BOOTLOADER`" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:267 msgid "" "With `NANO_BOOTLOADER` a bootloader file can be chosen. The most common " "possible options are between [.filename]#boot0sio# and [.filename]#boot0# " "depending on whether the appliance has a serial port or not. It is best to " "avoid supplying a different bootloader, but it is possible. To do so, it is " "best to have checked the extref:{handbook}boot[FreeBSD Handbook] chapter on " "the boot process." msgstr "" "С помощью `NANO_BOOTLOADER` можно выбрать файл загрузчика. Наиболее " "распространённые варианты — [.filename]#boot0sio# и [.filename]#boot0#, в " "зависимости от наличия последовательного порта у устройства. Лучше не " "указывать другой загрузчик, но это возможно. Для этого рекомендуется " "предварительно ознакомиться с extref:{handbook}boot[главой FreeBSD Handbook] " "о процессе загрузки." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:274 msgid "" "With `NANO_BOOT0CFG`, the booting process can be tweaked, like selecting on " "which partition the NanoBSD image will actually boot. It is best to check " "the man:boot0cfg[8] page before changing the default value of this " "variable. One option that could be interesting to change is the timeout of " "the booting procedure. To do so, the `NANO_BOOT0CFG` variable can be " "changed to `\"-o packet -s 1 -m 3 -t 36\"`. That way the booting process " "would start after approximately 2 seconds; because it is rare that waiting " "10 seconds before actually booting is desired." msgstr "" "С помощью `NANO_BOOT0CFG` можно настроить процесс загрузки, например, " "выбрать раздел, с которого будет загружаться образ NanoBSD. Перед изменением " "значения этой переменной рекомендуется ознакомиться со страницей руководства " "man:boot0cfg[8]. Один из интересных параметров, который можно изменить, — " "это таймаут процедуры загрузки. Для этого переменную `NANO_BOOT0CFG` можно " "изменить на `\"-o packet -s 1 -m 3 -t 36\"`. В этом случае процесс загрузки " "начнётся примерно через 2 секунды, так как редко возникает необходимость " "ждать 10 секунд перед началом загрузки." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:277 msgid "" "Good to know: the `NANO_BOOT2CFG` variable is only used in the " "`cust_comconsole` routine that can be called at the `NANO_CUSTOMIZE` step if " "the appliance has a serial port and all console input and output has to take " "place through it. Be sure to check the relevant parameters of the serial " "port, as setting a bad parameter value can make it useless." msgstr "" "Хорошо знать: переменная `NANO_BOOT2CFG` используется только в подпрограмме " "`cust_comconsole`, которая может вызываться на этапе `NANO_CUSTOMIZE`, если " "устройство имеет последовательный порт и весь ввод и вывод консоли должен " "осуществляться через него. Обязательно проверьте соответствующие параметры " "последовательного порта, так как установка некорректного значения параметра " "может сделать его бесполезным." #. type: Title ===== #: documentation/content/en/articles/nanobsd/_index.adoc:278 #, no-wrap msgid "Disk Image Creation" msgstr "Создание образа диска" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:282 msgid "" "In the end of the boot process is the disk image creation. With this step, " "the NanoBSD script provides a file that can simply be copied onto a disk for " "the appliance, and that will make it boot and start." msgstr "" "В конце процесса загрузки происходит создание образа диска. На этом этапе " "скрипт NanoBSD предоставляет файл, который можно просто скопировать на диск " "для устройства, и это позволит ему загрузиться и запуститься." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:284 msgid "" "There are many variables that need to be set just right for the script to " "produce a usable disk image." msgstr "" "Существует множество переменных, которые должны быть настроены правильно, " "чтобы скрипт создал пригодный для использования образ диска." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:286 msgid "" "The `NANO_DRIVE` variable must be set to the drive name of the media at " "runtime. Usually, the default value `ada0`, which represents the first `IDE`/" "`ATA`/`SATA` device on the appliance is expected to be the correct one, but " "a different type of storage could also be used - like a USB key, in which " "case, it would rather be `da0`." msgstr "" "Переменная `NANO_DRIVE` должна быть установлена в имя накопителя носителя во " "время выполнения. Обычно ожидается, что значение по умолчанию `ada0`, " "которое представляет первое устройство `IDE`/`ATA`/`SATA` на устройстве, " "будет правильным, но также может использоваться другой тип накопителя — " "например, USB-ключ, в этом случае это скорее будет `da0`." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:287 msgid "" "The `NANO_MEDIASIZE` variable must be set to the size (in 512-byte sectors) " "of the storage media that will be used. If you set it wrong, it is possible " "that the NanoBSD image will not boot at all, and a message at boot time will " "be warning about incorrect disk geometry." msgstr "" "Переменная `NANO_MEDIASIZE` должна быть установлена в значение размера (в " "секторах по 512 байт) носителя данных, который будет использоваться. Если " "задать её неправильно, образ NanoBSD может вообще не загрузиться, а во время " "загрузки появится сообщение о некорректной геометрии диска." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:289 msgid "" "The [.filename]#/etc#, [.filename]#/var#, and [.filename]#/tmp# directories " "are allocated as man:md[4] (malloc) disks at boot time; so their sizes can " "be tailored to suit the appliance needs. The `NANO_RAM_ETCSIZE` variable " "sets the size of the [.filename]#/etc#; and the `NANO_RAM_TMPVARSIZE` " "variable sets the size of both the [.filename]#/var# and [.filename]#/tmp# " "directory, as [.filename]#/tmp# is symbolically linked to [.filename]#/var/" "tmp#. By default, both malloc disks sizes are set at 20MB each. They can " "always be changed, but usually the [.filename]#/etc# does not grow too much " "in size, so 20MB is a good starting point, whereas the [.filename]#/var# and " "especially [.filename]#/tmp# can grow much larger if not careful about it. " "For memory constrained systems, smaller filesystem sizes may be chosen." msgstr "" "Каталоги [.filename]#/etc#, [.filename]#/var# и [.filename]#/tmp# выделяются " "как диски man:md[4] (malloc) при загрузке; их размеры могут быть настроены в " "соответствии с потребностями устройства. Переменная `NANO_RAM_ETCSIZE` " "задаёт размер [.filename]#/etc#, а переменная `NANO_RAM_TMPVARSIZE` " "определяет размер как [.filename]#/var#, так и [.filename]#/tmp#, поскольку " "[.filename]#/tmp# символически ссылается на [.filename]#/var/tmp#. По " "умолчанию размер обоих дисков malloc установлен в 20 МБ каждый. Их можно " "изменить, но обычно [.filename]#/etc# не сильно увеличивается в размере, " "поэтому 20 МБ — хорошая начальная точка, тогда как [.filename]#/var# и " "особенно [.filename]#/tmp# могут стать значительно больше, если не следить " "за ними. Для систем с ограниченной памятью можно выбрать меньшие размеры " "файловых систем." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:290 msgid "" "As NanoBSD is mainly designed to build a system image for an appliance, it " "is assumed that the storage media used will be relatively small. For that " "reason, the filesystem that is laid out is configured to have a small block " "size (4Kb) and a small fragment size (512b). The configuration options of " "the filesystem can be modified through the `NANO_NEWFS` variable, but the " "syntax must respect the man:newfs[8] command format. Also, by default, the " "filesystem has Soft Updates enabled. The extref:{handbook}[FreeBSD Handbook] " "can be checked about this." msgstr "" "Поскольку NanoBSD в основном предназначен для создания образа системы для " "устройства, предполагается, что используемые носители данных будут " "относительно небольшими. По этой причине файловая система настроена на " "использование небольшого размера блока (4 Кб) и небольшого размера фрагмента " "(512 байт). Параметры конфигурации файловой системы можно изменить с помощью " "переменной `NANO_NEWFS`, но синтаксис должен соответствовать формату команды " "man:newfs[8]. Кроме того, по умолчанию в файловой системе включены Soft " "Updates. Подробнее об этом можно узнать в extref:{handbook}[FreeBSD " "Handbook]." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:291 msgid "" "The different partition sizes can be set through the use of `NANO_CODESIZE`, " "`NANO_CONFSIZE`, and `NANO_DATASIZE` as a multiple of 512-byte sectors. " "`NANO_CODESIZE` defines the size of the first two image partitions: `code#1` " "and `code#2`. They have to be big enough to hold all the files that will be " "produced as a result of the `buildworld` and `buildkernel` processes. " "`NANO_CONFSIZE` defines the size of the configuration file partition, so it " "does not need to be very big; but do not make it so small that it will not " "hold all configuration files. Finally, `NANO_DATASIZE` defines the size of " "an optional partition, that can be used on the appliance. The last partition " "can be used, for example, to keep files created on the fly on disk." msgstr "" "Различные размеры разделов могут быть заданы с использованием `NANO_CODESIZE`" ", `NANO_CONFSIZE` и `NANO_DATASIZE` в виде кратного 512-байтным секторам. " "`NANO_CODESIZE` определяет размер первых двух разделов образа: `code#1` и " "`code#2`. Они должны быть достаточно большими, чтобы вместить все файлы, " "созданные в результате процессов `buildworld` и `buildkernel`. " "`NANO_CONFSIZE` определяет размер раздела для конфигурационных файлов, " "поэтому он не должен быть очень большим; однако не стоит делать его слишком " "маленьким, чтобы он мог вместить все конфигурационные файлы. Наконец, " "`NANO_DATASIZE` определяет размер дополнительного раздела, который может " "использоваться на устройстве. Последний раздел может быть использован, " "например, для хранения файлов, создаваемых на лету на диске." #. type: Title ==== #: documentation/content/en/articles/nanobsd/_index.adoc:292 #, no-wrap msgid "Custom Functions" msgstr "Пользовательские функции" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:296 msgid "" "It is possible to fine-tune NanoBSD using shell functions in the " "configuration file. The following example illustrates the basic model of " "custom functions:" msgstr "" "Возможно тонко настроить NanoBSD с помощью функций оболочки в " "конфигурационном файле. Следующий пример иллюстрирует базовую модель " "пользовательских функций:" #. type: delimited block . 4 #: documentation/content/en/articles/nanobsd/_index.adoc:304 #, no-wrap msgid "" "cust_foo () (\n" "\techo \"bar=baz\" > \\\n" "\t\t${NANO_WORLDDIR}/etc/foo\n" ")\n" "customize_cmd cust_foo\n" msgstr "" "cust_foo () (\n" "\techo \"bar=baz\" > \\\n" "\t\t${NANO_WORLDDIR}/etc/foo\n" ")\n" "customize_cmd cust_foo\n" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:307 msgid "" "A more useful example of a customization function is the following, which " "changes the default size of the [.filename]#/etc# directory from 5MB to 30MB:" msgstr "" "Более полезный пример функции настройки — следующий, который изменяет размер " "каталога [.filename]#/etc# по умолчанию с 5 МБ на 30 МБ:" #. type: delimited block . 4 #: documentation/content/en/articles/nanobsd/_index.adoc:315 #, no-wrap msgid "" "cust_etc_size () (\n" "\tcd ${NANO_WORLDDIR}/conf\n" "\techo 30000 > default/etc/md_size\n" ")\n" "customize_cmd cust_etc_size\n" msgstr "" "cust_etc_size () (\n" "\tcd ${NANO_WORLDDIR}/conf\n" "\techo 30000 > default/etc/md_size\n" ")\n" "customize_cmd cust_etc_size\n" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:318 msgid "" "There are a few default pre-defined customization functions ready for use:" msgstr "" "Существует несколько предопределённых функций для настройки, готовых к " "использованию:" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:320 msgid "" "`cust_comconsole` - Disables man:getty[8] on the VGA devices (the [." "filename]#/dev/ttyv*# device nodes) and enables the use of the COM1 serial " "port as the system console." msgstr "" "`cust_comconsole` - Отключает man:getty[8] на VGA-устройствах (узлы " "устройств [.filename]#/dev/ttyv*#) и позволяет использовать последовательный " "порт COM1 в качестве системной консоли." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:321 msgid "`cust_allow_ssh_root` - Allow `root` to login via man:sshd[8]." msgstr "`cust_allow_ssh_root` - Разрешить `root` входить через man:sshd[8]." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:322 msgid "" "`cust_install_files` - Installs files from the [.filename]#nanobsd/Files# " "directory, which contains some useful scripts for system administration." msgstr "" "`cust_install_files` - Устанавливает файлы из каталога [.filename]#nanobsd/" "Files#, который содержит полезные скрипты для администрирования системы." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:323 msgid "" "`cust_pkgng` - Installs packages from the [.filename]#nanobsd/Pkg# directory " "(needs also pkg-* package to bootstrap)." msgstr "" "`cust_pkgng` - Устанавливает пакеты из каталога [.filename]#nanobsd/Pkg# " "(также требуется пакет pkg-* для начальной загрузки)." #. type: Title ==== #: documentation/content/en/articles/nanobsd/_index.adoc:324 #, no-wrap msgid "Adding Packages" msgstr "Добавление пакетов" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:327 msgid "" "Packages can be added to a NanoBSD image, to provide specific " "functionalities on the appliance. To do so, either:" msgstr "" "Пакеты могут быть добавлены в образ NanoBSD для обеспечения специфических " "функциональных возможностей устройства. Для этого можно:" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:329 msgid "Add the `cust_pkgng` to the `NANO_CUSTOMIZE` variable, or" msgstr "Добавьте `cust_pkgng` в переменную `NANO_CUSTOMIZE` или" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:330 msgid "" "Add a `'customize_cmd cust_pkgng'` command in a customized configuration " "file." msgstr "" "Добавьте команду `'customize_cmd cust_pkgng'` в настраиваемый " "конфигурационный файл." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:333 msgid "" "Both methods achieve the same result: launching the `cust_pkgng` routine. " "This routine will go through `NANO_PACKAGE_DIR` directory to find either all " "packages or just the list of packages in the `NANO_PACKAGE_LIST` variable." msgstr "" "Оба метода приводят к одному результату: запуск процедуры `cust_pkgng`. Эта " "процедура проверит каталог `NANO_PACKAGE_DIR` для поиска всех пакетов или " "только списка пакетов, указанных в переменной `NANO_PACKAGE_LIST`." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:339 msgid "" "It is common, when installing applications through pkg on a standard FreeBSD " "environment, that the install process puts configuration files, in the [." "filename]#usr/local/etc# directory, and startup scripts in the [.filename]#/" "usr/local/etc/rc.d# directory. So, after the required packages have been " "installed, they need to be configured in order for them to start right out " "of the box. To do so, the necessary configuration files have to be " "installed in the correct directories. This can be achieved by writing " "dedicated routines or the generic `cust_install_files` routine can be used " "to lay out files properly from the [.filename]#/usr/src/tools/tools/nanobsd/" "Files# directory. Usually a statement, sometimes multiple statements, in " "the [.filename]#/etc/rc.conf# also needs to be added for each package." msgstr "" "Обычно при установке приложений через pkg в стандартной среде FreeBSD " "процесс установки размещает конфигурационные файлы в каталоге [." "filename]#usr/local/etc#, а скрипты запуска — в каталоге [.filename]#/usr/" "local/etc/rc.d#. Поэтому после установки необходимых пакетов их нужно " "настроить, чтобы они запускались сразу после установки. Для этого необходимо " "разместить соответствующие конфигурационные файлы в правильных каталогах. " "Это можно сделать, написав специализированные процедуры, или использовать " "общую процедуру `cust_install_files` для корректного размещения файлов из " "каталога [.filename]#/usr/src/tools/tools/nanobsd/Files#. Обычно также " "требуется добавить одну или несколько записей в файл [.filename]#/etc/rc." "conf# для каждого пакета." #. type: Title ==== #: documentation/content/en/articles/nanobsd/_index.adoc:340 #, no-wrap msgid "Configuration File Example" msgstr "Пример файла конфигурации" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:343 msgid "" "A complete example of a configuration file for building a custom NanoBSD " "image can be:" msgstr "" "Полный пример конфигурационного файла для создания пользовательского образа " "NanoBSD может выглядеть следующим образом:" #. type: delimited block . 4 #: documentation/content/en/articles/nanobsd/_index.adoc:350 #, no-wrap msgid "" "NANO_NAME=custom\n" "NANO_SRC=/usr/src\n" "NANO_KERNEL=MYKERNEL\n" "NANO_IMAGES=2\n" msgstr "" "NANO_NAME=custom\n" "NANO_SRC=/usr/src\n" "NANO_KERNEL=MYKERNEL\n" "NANO_IMAGES=2\n" #. type: delimited block . 4 #: documentation/content/en/articles/nanobsd/_index.adoc:356 #, no-wrap msgid "" "CONF_BUILD='\n" "WITHOUT_KLDLOAD=YES\n" "WITHOUT_NETGRAPH=YES\n" "WITHOUT_PAM=YES\n" "'\n" msgstr "" "CONF_BUILD='\n" "WITHOUT_KLDLOAD=YES\n" "WITHOUT_NETGRAPH=YES\n" "WITHOUT_PAM=YES\n" "'\n" #. type: delimited block . 4 #: documentation/content/en/articles/nanobsd/_index.adoc:372 #, no-wrap msgid "" "CONF_INSTALL='\n" "WITHOUT_ACPI=YES\n" "WITHOUT_BLUETOOTH=YES\n" "WITHOUT_FORTRAN=YES\n" "WITHOUT_HTML=YES\n" "WITHOUT_LPR=YES\n" "WITHOUT_MAN=YES\n" "WITHOUT_SENDMAIL=YES\n" "WITHOUT_SHAREDOCS=YES\n" "WITHOUT_EXAMPLES=YES\n" "WITHOUT_INSTALLLIB=YES\n" "WITHOUT_CALENDAR=YES\n" "WITHOUT_MISC=YES\n" "WITHOUT_SHARE=YES\n" "'\n" msgstr "" "CONF_INSTALL='\n" "WITHOUT_ACPI=YES\n" "WITHOUT_BLUETOOTH=YES\n" "WITHOUT_FORTRAN=YES\n" "WITHOUT_HTML=YES\n" "WITHOUT_LPR=YES\n" "WITHOUT_MAN=YES\n" "WITHOUT_SENDMAIL=YES\n" "WITHOUT_SHAREDOCS=YES\n" "WITHOUT_EXAMPLES=YES\n" "WITHOUT_INSTALLLIB=YES\n" "WITHOUT_CALENDAR=YES\n" "WITHOUT_MISC=YES\n" "WITHOUT_SHARE=YES\n" "'\n" #. type: delimited block . 4 #: documentation/content/en/articles/nanobsd/_index.adoc:383 #, no-wrap msgid "" "CONF_WORLD='\n" "WITHOUT_BIND=YES\n" "WITHOUT_MODULES=YES\n" "WITHOUT_KERBEROS=YES\n" "WITHOUT_GAMES=YES\n" "WITHOUT_RESCUE=YES\n" "WITHOUT_LOCALES=YES\n" "WITHOUT_SYSCONS=YES\n" "WITHOUT_INFO=YES\n" "'\n" msgstr "" "CONF_WORLD='\n" "WITHOUT_BIND=YES\n" "WITHOUT_MODULES=YES\n" "WITHOUT_KERBEROS=YES\n" "WITHOUT_GAMES=YES\n" "WITHOUT_RESCUE=YES\n" "WITHOUT_LOCALES=YES\n" "WITHOUT_SYSCONS=YES\n" "WITHOUT_INFO=YES\n" "'\n" #. type: delimited block . 4 #: documentation/content/en/articles/nanobsd/_index.adoc:385 #, no-wrap msgid "FlashDevice SanDisk 1G\n" msgstr "FlashDevice SanDisk 1G\n" #. type: delimited block . 4 #: documentation/content/en/articles/nanobsd/_index.adoc:390 #, no-wrap msgid "" "cust_nobeastie() (\n" "\ttouch ${NANO_WORLDDIR}/boot/loader.conf\n" "\techo \"beastie_disable=\\\"YES\\\"\" >> ${NANO_WORLDDIR}/boot/loader.conf\n" ")\n" msgstr "" "cust_nobeastie() (\n" "\ttouch ${NANO_WORLDDIR}/boot/loader.conf\n" "\techo \"beastie_disable=\\\"YES\\\"\" >> ${NANO_WORLDDIR}/boot/loader.conf\n" ")\n" #. type: delimited block . 4 #: documentation/content/en/articles/nanobsd/_index.adoc:395 #, no-wrap msgid "" "customize_cmd cust_comconsole\n" "customize_cmd cust_install_files\n" "customize_cmd cust_allow_ssh_root\n" "customize_cmd cust_nobeastie\n" msgstr "" "customize_cmd cust_comconsole\n" "customize_cmd cust_install_files\n" "customize_cmd cust_allow_ssh_root\n" "customize_cmd cust_nobeastie\n" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:399 msgid "" "All the build and install compilation options can be found in the man:src." "conf[5] man page, but not all options can or should be used when building a " "NanoBSD image. The build and install options should be defined according to " "the needs of the image being built." msgstr "" "Все параметры сборки и установки можно найти на странице Справочника man:src." "conf[5], но не все параметры можно или следует использовать при создании " "образа NanoBSD. Параметры сборки и установки должны определяться в " "соответствии с потребностями создаваемого образа." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:403 msgid "" "For example, the ftp client and server might not be needed. Adding " "`WITHOUT_FTP=TRUE` to a configuration file in the `CONF_BUILD` section will " "avoid having them built. Also, if the NanoBSD appliance will not be used to " "build programs then it is possible to add the `WITHOUT_BINUTILS=TRUE` in the " "`CONF_INSTALL` section; but not in the `CONF_BUILD` section as they will be " "used to build the NanoBSD image." msgstr "" "Например, FTP-клиент и сервер могут не потребоваться. Добавление " "`WITHOUT_FTP=TRUE` в файл конфигурации в разделе `CONF_BUILD` позволит " "избежать их сборки. Также, если устройство NanoBSD не будет использоваться " "для сборки программ, можно добавить `WITHOUT_BINUTILS=TRUE` в раздел " "`CONF_INSTALL`, но не в раздел `CONF_BUILD`, так как они будут " "использоваться для сборки образа NanoBSD." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:405 msgid "" "Not building a particular set of programs - through a compilation option - " "shortens the overall building time and lowers the required size for the disk " "image, whereas not installing the same specific set of programs does not " "lower the overall building time." msgstr "" "Исключение сборки определённого набора программ через параметры компиляции — " "сокращает общее время сборки и уменьшает требуемый размер дискового образа, " "тогда как отсутствие установки того же набора программ не сокращает общее " "время сборки." #. type: Title === #: documentation/content/en/articles/nanobsd/_index.adoc:406 #, no-wrap msgid "Updating NanoBSD" msgstr "Обновление NanoBSD" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:409 msgid "The update process of NanoBSD is relatively simple:" msgstr "Процесс обновления NanoBSD относительно прост:" #. type: delimited block = 4 #: documentation/content/en/articles/nanobsd/_index.adoc:413 msgid "Build a new NanoBSD image, as usual." msgstr "Соберите новый образ NanoBSD, как обычно." #. type: delimited block = 4 #: documentation/content/en/articles/nanobsd/_index.adoc:414 msgid "" "Upload the new image into an unused partition of a running NanoBSD appliance." msgstr "" "Загрузите новый образ в неиспользуемый раздел работающего устройства NanoBSD." #. type: delimited block = 4 #: documentation/content/en/articles/nanobsd/_index.adoc:416 msgid "" "The most important difference of this step from the initial NanoBSD " "installation is that now instead of using [.filename]#\\_.disk.full# (which " "contains an image of the entire disk), the [.filename]#_.disk.image# image " "is installed (which contains an image of a single system partition)." msgstr "" "Важнейшее отличие этого шага от первоначальной установки NanoBSD заключается " "в том, что теперь вместо использования [.filename]#\\_.disk.full# (который " "содержит образ всего диска), устанавливается образ [.filename]#_.disk.image# " "(который содержит образ одного системного раздела)." #. type: delimited block = 4 #: documentation/content/en/articles/nanobsd/_index.adoc:417 msgid "Reboot, and start the system from the newly installed partition." msgstr "" "Перезагрузите систему и запустите её с только что установленного раздела." #. type: delimited block = 4 #: documentation/content/en/articles/nanobsd/_index.adoc:418 msgid "If all goes well, the upgrade is finished." msgstr "Если все прошло успешно, обновление завершено." #. type: delimited block = 4 #: documentation/content/en/articles/nanobsd/_index.adoc:419 msgid "" "If anything goes wrong, reboot back into the previous partition (which " "contains the old, working image), to restore system functionality as fast as " "possible. Fix any problems of the new build, and repeat the process." msgstr "" "Если что-то пойдет не так, перезагрузитесь обратно в предыдущий раздел " "(который содержит старую, рабочую версию), чтобы восстановить " "работоспособность системы как можно быстрее. Исправьте все проблемы новой " "сборки и повторите процесс." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:422 msgid "" "To install new image onto the running NanoBSD system, it is possible to use " "either the [.filename]#updatep1# or [.filename]#updatep2# script located in " "the [.filename]#/root# directory, depending from which partition is running " "the current system." msgstr "" "Для установки нового образа на работающую систему NanoBSD можно использовать " "скрипт [.filename]#updatep1# или [.filename]#updatep2#, расположенный в " "каталоге [.filename]#/root#, в зависимости от того, с какого раздела " "запущена текущая система." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:424 msgid "" "According to which services are available on the host serving the new " "NanoBSD image and what type of transfer is preferred, it is possible to use " "one of these three methods:" msgstr "" "В зависимости от того, какие службы доступны на хосте, предоставляющем новый " "образ NanoBSD, и какой тип передачи предпочтителен, можно использовать один " "из следующих трёх способов:" #. type: Title ==== #: documentation/content/en/articles/nanobsd/_index.adoc:425 #, no-wrap msgid "Using man:ftp[1]" msgstr "Использование man:ftp[1]" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:428 msgid "If the transfer speed is most important, use this example:" msgstr "" "Если скорость передачи данных стоит на первом месте, используйте этот пример:" #. type: delimited block . 4 #: documentation/content/en/articles/nanobsd/_index.adoc:433 #, no-wrap msgid "" "# ftp myhost\n" "get _.disk.image \"| sh updatep1\"\n" msgstr "" "# ftp myhost\n" "get _.disk.image \"| sh updatep1\"\n" #. type: Title ==== #: documentation/content/en/articles/nanobsd/_index.adoc:435 #, no-wrap msgid "Using man:ssh[1]" msgstr "Использование man:ssh[1]" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:438 msgid "If a secure transfer is preferred, consider using this example:" msgstr "" "Если предпочтителен безопасный способ передачи, рассмотрите следующий пример:" #. type: delimited block . 4 #: documentation/content/en/articles/nanobsd/_index.adoc:442 #, no-wrap msgid "# ssh myhost cat _.disk.image.gz | zcat | sh updatep1\n" msgstr "# ssh myhost cat _.disk.image.gz | zcat | sh updatep1\n" #. type: Title ==== #: documentation/content/en/articles/nanobsd/_index.adoc:444 #, no-wrap msgid "Using man:nc[1]" msgstr "Использование man:nc[1]" #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:447 msgid "" "Try this example if the remote host is not running the man:ftpd[8] or man:" "sshd[8] service:" msgstr "" "Попробуйте этот пример, если на удалённом хосте не запущены ни служба " "man:ftpd[8], ни служба man:sshd[8]:" #. type: delimited block = 4 #: documentation/content/en/articles/nanobsd/_index.adoc:451 msgid "" "First, open a TCP listener on the host serving the image, and make it send " "the image to the client:" msgstr "" "Сначала откройте TCP-слушатель на хосте, обслуживающем образ, и настройте " "его на отправку образа клиенту:" #. type: delimited block . 4 #: documentation/content/en/articles/nanobsd/_index.adoc:455 #, no-wrap msgid "myhost# nc -l 2222 < _.disk.image\n" msgstr "myhost# nc -l 2222 < _.disk.image\n" #. type: delimited block = 6 #: documentation/content/en/articles/nanobsd/_index.adoc:460 msgid "" "Make sure that the chosen port is not blocked by the firewall to receive " "incoming connections from the NanoBSD host." msgstr "" "Убедитесь, что выбранный порт не заблокирован межсетевым экраном для приёма " "входящих соединений с хоста NanoBSD." #. type: Plain text #: documentation/content/en/articles/nanobsd/_index.adoc:462 msgid "" "Connect to the host serving the new image, and execute the [." "filename]#updatep1# script:" msgstr "" "Подключитесь к хосту, предоставляющему новый образ, и выполните скрипт [." "filename]#updatep1#:" #. type: delimited block . 4 #: documentation/content/en/articles/nanobsd/_index.adoc:466 #, no-wrap msgid "# nc myhost 2222 | sh updatep1\n" msgstr "# nc myhost 2222 | sh updatep1\n" diff --git a/documentation/content/ru/articles/pgpkeys/_index.adoc b/documentation/content/ru/articles/pgpkeys/_index.adoc index 6bad1ebbd5..fdf18ce275 100644 --- a/documentation/content/ru/articles/pgpkeys/_index.adoc +++ b/documentation/content/ru/articles/pgpkeys/_index.adoc @@ -1,1569 +1,1581 @@ --- description: 'Список OpenPGP-ключей, которые можно использовать для проверки подписей или отправки зашифрованной электронной почты офицерам или разработчикам FreeBSD.org.' tags: ["OpenPGP", "Developers", "Officers", "FreeBSD"] title: 'Ключи OpenPGP' --- = Ключи OpenPGP :doctype: article :toc: macro :toclevels: 1 :icons: font :sectnums: :sectnumlevels: 6 :source-highlighter: rouge :experimental: :images-path: articles/pgpkeys/ ifdef::env-beastie[] ifdef::backend-html5[] include::shared/authors.adoc[] include::shared/mirrors.adoc[] include::shared/releases.adoc[] include::shared/attributes/attributes-{{% lang %}}.adoc[] include::shared/{{% lang %}}/teams.adoc[] include::shared/{{% lang %}}/mailing-lists.adoc[] include::shared/{{% lang %}}/urls.adoc[] :imagesdir: ../../../images/{images-path} :include-path: static/pgpkeys/ endif::[] ifdef::backend-pdf,backend-epub3[] include::../../../../shared/asciidoctor.adoc[] // PGP keys are not included during the build // See 29e47423be969b7fcc7125977c1b22ddd33fc671 revision // (a wrong path is used as a workaround) :include-path: ../../../static/pgpkeys/ endif::[] endif::[] ifndef::env-beastie[] include::../../../../../shared/asciidoctor.adoc[] :include-path: ../../../static/pgpkeys/ endif::[] ''' toc::[] Эти OpenPGP-ключи можно использовать для проверки подписи или отправки зашифрованной электронной почты офицерам или разработчикам `FreeBSD.org`. Полный набор ключей можно загрузить по ссылке link:https://docs.FreeBSD.org/pgpkeys/pgpkeys.txt[pgpkeyring.txt]. //// Do not edit this file except as instructed by the addkey.sh script. See the README file in /data/pgpkeys for instructions. This article contains all the keys. The officer keys are also shown in the Handbook PGP keys chapter. //// [[pgpkeys-officers]] == Офицеры === {security-officer-name} `<{security-officer-email}>` include::{include-path}security-officer.key[] === {core-secretary-name} `<{core-secretary-email}>` include::{include-path}core-secretary.key[] === {portmgr-secretary-name} `<{portmgr-secretary-email}>` include::{include-path}portmgr-secretary.key[] === {doceng-secretary-name} `<{doceng-secretary-email}>` include::{include-path}doceng-secretary.key[] [[pgpkeys-core]] == Участники Основной команды (Core Team) === `{allanjude}` include::{include-path}allanjude.key[] === `{dch}` include::{include-path}dch.key[] === `{glebius}` include::{include-path}glebius.key[] === `{hrs}` include::{include-path}hrs.key[] === `{lwhsu}` include::{include-path}lwhsu.key[] === `{mat}` include::{include-path}mat.key[] === `{olivier}` include::{include-path}olivier.key[] === `{tcberner}` include::{include-path}tcberner.key[] [[pgpkeys-developers]] == Разработчики === `{jgh}` include::{include-path}jgh.key[] === `{ariff}` include::{include-path}ariff.key[] === `{tabthorpe}` include::{include-path}tabthorpe.key[] === `{eadler}` include::{include-path}eadler.key[] === `{pauamma}` include::{include-path}pauamma.key[] === `{shaun}` include::{include-path}shaun.key[] === `{brix}` include::{include-path}brix.key[] === `{mandree}` include::{include-path}mandree.key[] === `{will}` include::{include-path}will.key[] === `{dim}` include::{include-path}dim.key[] === `{anholt}` include::{include-path}anholt.key[] === `{fernape}` include::{include-path}fernape.key[] === `{mva}` include::{include-path}mva.key[] === `{araujo}` include::{include-path}araujo.key[] === `{mat}` include::{include-path}mat.key[] === `{syuu}` include::{include-path}syuu.key[] === `{asami}` include::{include-path}asami.key[] === `{jsa}` include::{include-path}jsa.key[] === `{jadawin}` include::{include-path}jadawin.key[] === `{jwb}` include::{include-path}jwb.key[] === `{dbaio}` include::{include-path}dbaio.key[] === `{timur}` include::{include-path}timur.key[] === `{jhb}` include::{include-path}jhb.key[] === `{gjb}` include::{include-path}gjb.key[] === `{snb}` include::{include-path}snb.key[] === `{barner}` include::{include-path}barner.key[] === `{lbartoletti}` include::{include-path}lbartoletti.key[] === `{art}` include::{include-path}art.key[] === `{tobez}` include::{include-path}tobez.key[] === `{damien}` include::{include-path}damien.key[] === `{bdragon}` include::{include-path}bdragon.key[] === `{tcberner}` include::{include-path}tcberner.key[] === `{tdb}` include::{include-path}tdb.key[] === `{mbr}` include::{include-path}mbr.key[] === `{bvs}` include::{include-path}bvs.key[] === `{jbo}` include::{include-path}jbo.key[] === `{novel}` include::{include-path}novel.key[] === `{garga}` include::{include-path}garga.key[] === `{kbowling}` include::{include-path}kbowling.key[] === `{alexbl}` include::{include-path}alexbl.key[] === `{ebrandi}` include::{include-path}ebrandi.key[] === `{harti}` include::{include-path}harti.key[] === `{obraun}` include::{include-path}obraun.key[] === `{makc}` include::{include-path}makc.key[] === `{jmb}` include::{include-path}jmb.key[] === `{dab}` include::{include-path}dab.key[] === `{antoine}` include::{include-path}antoine.key[] === `{db}` include::{include-path}db.key[] === `{brueffer}` include::{include-path}brueffer.key[] === `{markus}` include::{include-path}markus.key[] === `{br}` include::{include-path}br.key[] === `{jch}` include::{include-path}jch.key[] +=== `{laurent}` +include::{include-path}laurent.key[] + === `{jchandra}` include::{include-path}jchandra.key[] === `{jcamou}` include::{include-path}jcamou.key[] === `{acm}` include::{include-path}acm.key[] === `{olce}` include::{include-path}olce.key[] === `{gahr}` include::{include-path}gahr.key[] === `{dchagin}` include::{include-path}dchagin.key[] === `{perky}` include::{include-path}perky.key[] === `{jon}` include::{include-path}jon.key[] === `{jonathan}` include::{include-path}jonathan.key[] === `{loader}` include::{include-path}loader.key[] === `{luoqi}` include::{include-path}luoqi.key[] === `{ache}` include::{include-path}ache.key[] === `{melifaro}` include::{include-path}melifaro.key[] === `{cjh}` include::{include-path}cjh.key[] === `{davidch}` include::{include-path}davidch.key[] === `{milki}` include::{include-path}milki.key[] === `{cjc}` include::{include-path}cjc.key[] === `{marcus}` include::{include-path}marcus.key[] === `{fuz}` include::{include-path}fuz.key[] === `{nik}` include::{include-path}nik.key[] === `{benjsc}` include::{include-path}benjsc.key[] === `{lcook}` include::{include-path}lcook.key[] === `{ngie}` include::{include-path}ngie.key[] === `{rakuco}` include::{include-path}rakuco.key[] === `{alc}` include::{include-path}alc.key[] === `{olivier}` include::{include-path}olivier.key[] === `{dch}` include::{include-path}dch.key[] === `{bcran}` include::{include-path}bcran.key[] === `{cc}` include::{include-path}cc.key[] === `{culot}` include::{include-path}culot.key[] === `{alfredo}` include::{include-path}alfredo.key[] === `{bapt}` include::{include-path}bapt.key[] === `{ceri}` include::{include-path}ceri.key[] === `{edavis}` include::{include-path}edavis.key[] === `{alexey}` include::{include-path}alexey.key[] === `{bsd}` include::{include-path}bsd.key[] === `{carl}` include::{include-path}carl.key[] === `{carlavilla}` include::{include-path}carlavilla.key[] === `{vd}` include::{include-path}vd.key[] === `{rdivacky}` include::{include-path}rdivacky.key[] === `{danfe}` include::{include-path}danfe.key[] === `{dd}` include::{include-path}dd.key[] === `{bdrewery}` include::{include-path}bdrewery.key[] === `{gad}` include::{include-path}gad.key[] === `{kd}` include::{include-path}kd.key[] === `{olivierd}` include::{include-path}olivierd.key[] === `{bruno}` include::{include-path}bruno.key[] === `{ale}` include::{include-path}ale.key[] === `{jlduran}` include::{include-path}jlduran.key[] === `{nemysis}` include::{include-path}nemysis.key[] === `{peadar}` include::{include-path}peadar.key[] === `{deischen}` include::{include-path}deischen.key[] === `{diizzy}` include::{include-path}diizzy.key[] === `{ue}` include::{include-path}ue.key[] === `{madpilot}` include::{include-path}madpilot.key[] === `{rafan}` include::{include-path}rafan.key[] === `{kami}` include::{include-path}kami.key[] === `{farrokhi}` include::{include-path}farrokhi.key[] === `{jedgar}` include::{include-path}jedgar.key[] === `{mfechner}` include::{include-path}mfechner.key[] === `{feld}` include::{include-path}feld.key[] === `{green}` include::{include-path}green.key[] === `{fanf}` include::{include-path}fanf.key[] === `{blackend}` include::{include-path}blackend.key[] === `{petef}` include::{include-path}petef.key[] === `{decke}` include::{include-path}decke.key[] === `{landonf}` include::{include-path}landonf.key[] === `{billf}` include::{include-path}billf.key[] === `{grembo}` include::{include-path}grembo.key[] === `{sgalabov}` include::{include-path}sgalabov.key[] === `{kgalazka}` include::{include-path}kgalazka.key[] === `{avg}` include::{include-path}avg.key[] === `{tiga}` include::{include-path}tiga.key[] === `{beat}` include::{include-path}beat.key[] === `{sjg}` include::{include-path}sjg.key[] === `{gibbs}` include::{include-path}gibbs.key[] === `{pfg}` include::{include-path}pfg.key[] === `{girgen}` include::{include-path}girgen.key[] === `{eugen}` include::{include-path}eugen.key[] === `{pgollucci}` include::{include-path}pgollucci.key[] === `{trociny}` include::{include-path}trociny.key[] === `{dmgk}` include::{include-path}dmgk.key[] === `{daichi}` include::{include-path}daichi.key[] === `{grehan}` include::{include-path}grehan.key[] === `{jamie}` include::{include-path}jamie.key[] === `{adridg}` include::{include-path}adridg.key[] === `{wg}` include::{include-path}wg.key[] === `{bar}` include::{include-path}bar.key[] === `{jmg}` include::{include-path}jmg.key[] === `{mjg}` include::{include-path}mjg.key[] === `{jhale}` include::{include-path}jhale.key[] === `{jah}` include::{include-path}jah.key[] === `{dannyboy}` include::{include-path}dannyboy.key[] === `{dhartmei}` include::{include-path}dhartmei.key[] === `{ohauer}` include::{include-path}ohauer.key[] === `{ehaupt}` include::{include-path}ehaupt.key[] === `{jhay}` include::{include-path}jhay.key[] === `{bhd}` include::{include-path}bhd.key[] === `{sheldonh}` include::{include-path}sheldonh.key[] === `{mikeh}` include::{include-path}mikeh.key[] === `{mheinen}` include::{include-path}mheinen.key[] === `{niels}` include::{include-path}niels.key[] === `{ghelmer}` include::{include-path}ghelmer.key[] === `{mux}` include::{include-path}mux.key[] === `{wen}` include::{include-path}wen.key[] === `{dhn}` include::{include-path}dhn.key[] === `{jhibbits}` include::{include-path}jhibbits.key[] === `{jhixson}` include::{include-path}jhixson.key[] === `{pho}` include::{include-path}pho.key[] === `{oh}` include::{include-path}oh.key[] === `{mhorne}` include::{include-path}mhorne.key[] === `{bhughes}` include::{include-path}bhughes.key[] === `{sunpoet}` include::{include-path}sunpoet.key[] === `{lwhsu}` include::{include-path}lwhsu.key[] === `{foxfair}` include::{include-path}foxfair.key[] === `{whu}` include::{include-path}whu.key[] === `{chinsan}` include::{include-path}chinsan.key[] === `{zlei}` include::{include-path}zlei.key[] === `{davide}` include::{include-path}davide.key[] === `{jkh}` include::{include-path}jkh.key[] === `{versus}` include::{include-path}versus.key[] === `{pi}` include::{include-path}pi.key[] === `{weongyo}` include::{include-path}weongyo.key[] === `{peterj}` include::{include-path}peterj.key[] === `{jinmei}` include::{include-path}jinmei.key[] === `{ahze}` include::{include-path}ahze.key[] === `{markj}` include::{include-path}markj.key[] === `{trevor}` include::{include-path}trevor.key[] === `{erj}` include::{include-path}erj.key[] === `{allanjude}` include::{include-path}allanjude.key[] === `{bjk}` include::{include-path}bjk.key[] === `{phk}` include::{include-path}phk.key[] === `{pluknet}` include::{include-path}pluknet.key[] === `{cokane}` include::{include-path}cokane.key[] +=== `{mce}` +include::{include-path}mce.key[] + === `{karels}` include::{include-path}karels.key[] === `{kato}` include::{include-path}kato.key[] === `{vkashyap}` include::{include-path}vkashyap.key[] === `{pkubaj}` include::{include-path}pkubaj.key[] === `{kris}` include::{include-path}kris.key[] === `{keramida}` include::{include-path}keramida.key[] === `{fjoe}` include::{include-path}fjoe.key[] === `{manolis}` include::{include-path}manolis.key[] === `{stevek}` include::{include-path}stevek.key[] === `{jkim}` include::{include-path}jkim.key[] === `{zack}` include::{include-path}zack.key[] === `{akiyano}` include::{include-path}akiyano.key[] === `{jceel}` include::{include-path}jceel.key[] === `{andreas}` include::{include-path}andreas.key[] === `{kai}` include::{include-path}kai.key[] === `{corvink}` include::{include-path}corvink.key[] === `{jkois}` include::{include-path}jkois.key[] === `{sergei}` include::{include-path}sergei.key[] === `{maxim}` include::{include-path}maxim.key[] === `{taras}` include::{include-path}taras.key[] === `{tobik}` include::{include-path}tobik.key[] === `{jkoshy}` include::{include-path}jkoshy.key[] === `{wkoszek}` include::{include-path}wkoszek.key[] === `{ak}` include::{include-path}ak.key[] === `{gabor}` include::{include-path}gabor.key[] === `{anchie}` include::{include-path}anchie.key[] === `{rushani}` include::{include-path}rushani.key[] === `{kuriyama}` include::{include-path}kuriyama.key[] === `{rene}` include::{include-path}rene.key[] === `{jlaffaye}` include::{include-path}jlaffaye.key[] === `{clement}` include::{include-path}clement.key[] === `{mlaier}` include::{include-path}mlaier.key[] === `{martymac}` include::{include-path}martymac.key[] === `{glarkin}` include::{include-path}glarkin.key[] === `{dru}` include::{include-path}dru.key[] === `{lawrance}` include::{include-path}lawrance.key[] === `{njl}` include::{include-path}njl.key[] === `{jlh}` include::{include-path}jlh.key[] === `{leeym}` include::{include-path}leeym.key[] === `{sam}` include::{include-path}sam.key[] === `{jylefort}` include::{include-path}jylefort.key[] === `{grog}` include::{include-path}grog.key[] === `{oliver}` include::{include-path}oliver.key[] === `{netchild}` include::{include-path}netchild.key[] === `{leitao}` include::{include-path}leitao.key[] === `{ae}` include::{include-path}ae.key[] === `{lesi}` include::{include-path}lesi.key[] === `{achim}` include::{include-path}achim.key[] === `{cel}` include::{include-path}cel.key[] === `{glewis}` include::{include-path}glewis.key[] === `{vishwin}` include::{include-path}vishwin.key[] === `{delphij}` include::{include-path}delphij.key[] === `{avatar}` include::{include-path}avatar.key[] === `{ijliao}` include::{include-path}ijliao.key[] === `{rlibby}` include::{include-path}rlibby.key[] === `{pclin}` include::{include-path}pclin.key[] === `{yzlin}` include::{include-path}yzlin.key[] === `{linimon}` include::{include-path}linimon.key[] === `{arved}` include::{include-path}arved.key[] === `{dryice}` include::{include-path}dryice.key[] === `{nemoliu}` include::{include-path}nemoliu.key[] === `{kevlo}` include::{include-path}kevlo.key[] === `{zml}` include::{include-path}zml.key[] === `{nox}` include::{include-path}nox.key[] === `{avl}` include::{include-path}avl.key[] === `{scottl}` include::{include-path}scottl.key[] === `{rmacklem}` include::{include-path}rmacklem.key[] === `{vmaffione}` include::{include-path}vmaffione.key[] === `{bmah}` include::{include-path}bmah.key[] === `{rm}` include::{include-path}rm.key[] === `{mtm}` include::{include-path}mtm.key[] === `{dwmalone}` include::{include-path}dwmalone.key[] === `{christos}` include::{include-path}christos.key[] === `{marino}` include::{include-path}marino.key[] === `{emaste}` include::{include-path}emaste.key[] === `{cherry}` include::{include-path}cherry.key[] === `{matusita}` include::{include-path}matusita.key[] === `{mm}` include::{include-path}mm.key[] === `{sem}` include::{include-path}sem.key[] === `{rcm}` include::{include-path}rcm.key[] === `{mckusick}` include::{include-path}mckusick.key[] === `{tmclaugh}` include::{include-path}tmclaugh.key[] === `{jmelo}` include::{include-path}jmelo.key[] === `{mmel}` include::{include-path}mmel.key[] === `{jmmv}` include::{include-path}jmmv.key[] === `{kadesai}` include::{include-path}kadesai.key[] === `{ken}` include::{include-path}ken.key[] === `{markm}` include::{include-path}markm.key[] === `{dinoex}` include::{include-path}dinoex.key[] === `{sanpei}` include::{include-path}sanpei.key[] === `{rmh}` include::{include-path}rmh.key[] === `{driesm}` include::{include-path}driesm.key[] === `{jrm}` include::{include-path}jrm.key[] === `{freqlabs}` include::{include-path}freqlabs.key[] === `{mmoll}` include::{include-path}mmoll.key[] === `{cmt}` include::{include-path}cmt.key[] === `{stephen}` include::{include-path}stephen.key[] === `{marcel}` include::{include-path}marcel.key[] === `{dougm}` include::{include-path}dougm.key[] === `{kmoore}` include::{include-path}kmoore.key[] === `{marck}` include::{include-path}marck.key[] === `{mav}` include::{include-path}mav.key[] === `{rich}` include::{include-path}rich.key[] === `{knu}` include::{include-path}knu.key[] === `{tmm}` include::{include-path}tmm.key[] === `{max}` include::{include-path}max.key[] === `{maho}` include::{include-path}maho.key[] === `{yoichi}` include::{include-path}yoichi.key[] === `{bland}` include::{include-path}bland.key[] === `{gnn}` include::{include-path}gnn.key[] === `{khng}` include::{include-path}khng.key[] === `{simon}` include::{include-path}simon.key[] === `{rnoland}` include::{include-path}rnoland.key[] === `{anders}` include::{include-path}anders.key[] === `{lofi}` include::{include-path}lofi.key[] === `{obrien}` include::{include-path}obrien.key[] === `{olgeni}` include::{include-path}olgeni.key[] === `{philip}` include::{include-path}philip.key[] === `{jpaetzel}` include::{include-path}jpaetzel.key[] === `{zirias}` include::{include-path}zirias.key[] === `{hiren}` include::{include-path}hiren.key[] === `{hmp}` include::{include-path}hmp.key[] === `{fluffy}` include::{include-path}fluffy.key[] === `{sat}` include::{include-path}sat.key[] === `{np}` include::{include-path}np.key[] === `{royger}` include::{include-path}royger.key[] === `{rpaulo}` include::{include-path}rpaulo.key[] === `{misha}` include::{include-path}misha.key[] === `{dumbbell}` include::{include-path}dumbbell.key[] === `{rpokala}` include::{include-path}rpokala.key[] === `{mp}` include::{include-path}mp.key[] === `{roam}` include::{include-path}roam.key[] === `{den}` include::{include-path}den.key[] === `{csjp}` include::{include-path}csjp.key[] === `{grahamperrin}` include::{include-path}grahamperrin.key[] === `{gerald}` include::{include-path}gerald.key[] === `{scottph}` include::{include-path}scottph.key[] === `{jacula}` include::{include-path}jacula.key[] === `{0mp}` include::{include-path}0mp.key[] === `{jdp}` include::{include-path}jdp.key[] === `{krion}` include::{include-path}krion.key[] === `{vladlen}` include::{include-path}vladlen.key[] === `{sepotvin}` include::{include-path}sepotvin.key[] === `{cpm}` include::{include-path}cpm.key[] === `{markp}` include::{include-path}markp.key[] === `{alepulver}` include::{include-path}alepulver.key[] === `{kp}` include::{include-path}kp.key[] === `{thomas}` include::{include-path}thomas.key[] === `{hq}` include::{include-path}hq.key[] === `{bofh}` include::{include-path}bofh.key[] === `{fox}` include::{include-path}fox.key[] === `{lbr}` include::{include-path}lbr.key[] === `{crees}` include::{include-path}crees.key[] === `{rees}` include::{include-path}rees.key[] === `{mr}` include::{include-path}mr.key[] === `{bcr}` include::{include-path}bcr.key[] === `{trhodes}` include::{include-path}trhodes.key[] === `{benno}` include::{include-path}benno.key[] === `{beech}` include::{include-path}beech.key[] === `{roberto}` include::{include-path}roberto.key[] === `{rodrigc}` include::{include-path}rodrigc.key[] === `{michaelo}` include::{include-path}michaelo.key[] === `{igoro}` include::{include-path}igoro.key[] === `{dtxdf}` include::{include-path}dtxdf.key[] === `{ler}` include::{include-path}ler.key[] === `{leres}` include::{include-path}leres.key[] === `{robak}` include::{include-path}robak.key[] === `{guido}` include::{include-path}guido.key[] === `{rea}` include::{include-path}rea.key[] === `{ray}` include::{include-path}ray.key[] === `{niklas}` include::{include-path}niklas.key[] === `{salvadore}` include::{include-path}salvadore.key[] === `{bsam}` include::{include-path}bsam.key[] === `{marks}` include::{include-path}marks.key[] === `{bschmidt}` include::{include-path}bschmidt.key[] === `{wosch}` include::{include-path}wosch.key[] === `{cy}` include::{include-path}cy.key[] === `{das}` include::{include-path}das.key[] === `{scheidell}` include::{include-path}scheidell.key[] === `{matthew}` include::{include-path}matthew.key[] === `{tmseck}` include::{include-path}tmseck.key[] === `{johans}` include::{include-path}johans.key[] === `{bakul}` include::{include-path}bakul.key[] === `{gshapiro}` include::{include-path}gshapiro.key[] === `{wxs}` include::{include-path}wxs.key[] === `{nork}` include::{include-path}nork.key[] === `{syrinx}` include::{include-path}syrinx.key[] === `{vanilla}` include::{include-path}vanilla.key[] === `{ashafer}` include::{include-path}ashafer.key[] === `{ashish}` include::{include-path}ashish.key[] === `{asiciliano}` include::{include-path}asiciliano.key[] === `{chs}` include::{include-path}chs.key[] === `{bms}` include::{include-path}bms.key[] === `{demon}` include::{include-path}demon.key[] === `{jesper}` include::{include-path}jesper.key[] === `{scop}` include::{include-path}scop.key[] === `{anray}` include::{include-path}anray.key[] === `{flo}` include::{include-path}flo.key[] === `{glebius}` include::{include-path}glebius.key[] === `{kensmith}` include::{include-path}kensmith.key[] === `{ben}` include::{include-path}ben.key[] === `{des}` include::{include-path}des.key[] === `{sobomax}` include::{include-path}sobomax.key[] === `{asomers}` include::{include-path}asomers.key[] === `{brian}` include::{include-path}brian.key[] === `{sson}` include::{include-path}sson.key[] === `{nsouch}` include::{include-path}nsouch.key[] === `{ssouhlal}` include::{include-path}ssouhlal.key[] === `{loos}` include::{include-path}loos.key[] === `{brnrd}` include::{include-path}brnrd.key[] === `{rink}` include::{include-path}rink.key[] === `{vsevolod}` include::{include-path}vsevolod.key[] === `{pstef}` include::{include-path}pstef.key[] === `{zi}` include::{include-path}zi.key[] === `{lstewart}` include::{include-path}lstewart.key[] === `{murray}` include::{include-path}murray.key[] === `{vs}` include::{include-path}vs.key[] === `{xride}` include::{include-path}xride.key[] === `{marius}` include::{include-path}marius.key[] === `{cs}` include::{include-path}cs.key[] === `{clsung}` include::{include-path}clsung.key[] === `{gsutter}` include::{include-path}gsutter.key[] === `{metal}` include::{include-path}metal.key[] === `{ryusuke}` include::{include-path}ryusuke.key[] === `{nyan}` include::{include-path}nyan.key[] === `{sahil}` include::{include-path}sahil.key[] === `{tota}` include::{include-path}tota.key[] === `{romain}` include::{include-path}romain.key[] === `{eduardo}` include::{include-path}eduardo.key[] === `{sylvio}` include::{include-path}sylvio.key[] === `{itetcu}` include::{include-path}itetcu.key[] === `{mi}` include::{include-path}mi.key[] === `{gordon}` include::{include-path}gordon.key[] === `{lth}` include::{include-path}lth.key[] === `{fabient}` include::{include-path}fabient.key[] === `{thierry}` include::{include-path}thierry.key[] === `{thompsa}` include::{include-path}thompsa.key[] === `{flz}` include::{include-path}flz.key[] === `{jilles}` include::{include-path}jilles.key[] === `{ganbold}` include::{include-path}ganbold.key[] === `{tuexen}` include::{include-path}tuexen.key[] === `{gonzo}` include::{include-path}gonzo.key[] === `{uzsolt}` include::{include-path}uzsolt.key[] === `{ume}` include::{include-path}ume.key[] === `{ups}` include::{include-path}ups.key[] === `{fsu}` include::{include-path}fsu.key[] === `{mikael}` include::{include-path}mikael.key[] === `{manu}` include::{include-path}manu.key[] === `{ram}` include::{include-path}ram.key[] === `{bryanv}` include::{include-path}bryanv.key[] === `{nectar}` include::{include-path}nectar.key[] === `{avilla}` include::{include-path}avilla.key[] === `{nivit}` include::{include-path}nivit.key[] === `{ivoras}` include::{include-path}ivoras.key[] === `{stefan}` include::{include-path}stefan.key[] === `{kaiw}` include::{include-path}kaiw.key[] === `{adamw}` include::{include-path}adamw.key[] === `{naddy}` include::{include-path}naddy.key[] === `{peter}` include::{include-path}peter.key[] === `{nwhitehorn}` include::{include-path}nwhitehorn.key[] === `{obiwac}` include::{include-path}obiwac.key[] === `{miwi}` include::{include-path}miwi.key[] === `{nate}` include::{include-path}nate.key[] === `{twinterg}` include::{include-path}twinterg.key[] === `{def}` include::{include-path}def.key[] === `{wollman}` include::{include-path}wollman.key[] === `{joerg}` include::{include-path}joerg.key[] === `{ygy}` include::{include-path}ygy.key[] === `{emax}` include::{include-path}emax.key[] === `{oshogbo}` include::{include-path}oshogbo.key[] === `{andy}` include::{include-path}andy.key[] === `{riggs}` include::{include-path}riggs.key[] === `{egypcio}` include::{include-path}egypcio.key[] === `{bz}` include::{include-path}bz.key[] === `{dsl}` include::{include-path}dsl.key[] === `{zeising}` include::{include-path}zeising.key[] === `{phantom}` include::{include-path}phantom.key[] === `{tz}` include::{include-path}tz.key[] === `{rigoletto}` include::{include-path}rigoletto.key[] === `{kaktus}` include::{include-path}kaktus.key[] === `{samm}` include::{include-path}samm.key[] === `{arrowd}` include::{include-path}arrowd.key[] === `{ronald}` include::{include-path}ronald.key[] === `{meta}` include::{include-path}meta.key[] === `{rnagy}` include::{include-path}rnagy.key[] === `{vvd}` include::{include-path}vvd.key[] === `{gbe}` include::{include-path}gbe.key[] === `{bnovkov}` include::{include-path}bnovkov.key[] === `{ivy}` include::{include-path}ivy.key[] === `{khorben}` include::{include-path}khorben.key[] === `{vexeduxr}` include::{include-path}vexeduxr.key[] === `{alven}` include::{include-path}alven.key[] === `{pouria}` include::{include-path}pouria.key[] === `{siva}` include::{include-path}siva.key[] +=== `{nxjoseph}` +include::{include-path}nxjoseph.key[] + +=== `{kenrap}` +include::{include-path}kenrap.key[] + [[pgpkeys-other]] == Другие владельцы учётных записей === `{bk}` include::{include-path}bk.key[] === `{deb}` include::{include-path}deb.key[] === `{debdrup}` include::{include-path}debdrup.key[] === `{dutchdaemon}` include::{include-path}dutchdaemon.key[] === `{keymaster}` include::{include-path}keymaster.key[] === `{mwlucas}` include::{include-path}mwlucas.key[] === `{dhw}` include::{include-path}dhw.key[] === `{tpearson}` include::{include-path}tpearson.key[] diff --git a/documentation/content/ru/articles/pgpkeys/_index.po b/documentation/content/ru/articles/pgpkeys/_index.po index 3e9f5bc72e..f52f11a96e 100644 --- a/documentation/content/ru/articles/pgpkeys/_index.po +++ b/documentation/content/ru/articles/pgpkeys/_index.po @@ -1,3045 +1,3069 @@ # SOME DESCRIPTIVE TITLE # Copyright (C) YEAR The FreeBSD Project # This file is distributed under the same license as the FreeBSD Documentation package. # Vladlen Popolitov , 2025, 2026. msgid "" msgstr "" "Project-Id-Version: FreeBSD Documentation VERSION\n" -"POT-Creation-Date: 2026-02-22 15:58+0000\n" -"PO-Revision-Date: 2026-02-25 04:45+0000\n" +"POT-Creation-Date: 2026-05-09 23:29+0100\n" +"PO-Revision-Date: 2026-05-11 04:45+0000\n" "Last-Translator: Vladlen Popolitov \n" "Language-Team: Russian \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "X-Generator: Weblate 4.17\n" #. type: YAML Front Matter: description #: documentation/content/en/articles/pgpkeys/_index.adoc:1 #, no-wrap msgid "List of OpenPGP keys that can be used to verify a signature or send encrypted email to FreeBSD.org officers or developers." msgstr "Список OpenPGP-ключей, которые можно использовать для проверки подписей или отправки зашифрованной электронной почты офицерам или разработчикам FreeBSD.org." #. type: Title = #: documentation/content/en/articles/pgpkeys/_index.adoc:1 #: documentation/content/en/articles/pgpkeys/_index.adoc:7 #, no-wrap msgid "OpenPGP Keys" msgstr "Ключи OpenPGP" #. type: Plain text #: documentation/content/en/articles/pgpkeys/_index.adoc:45 msgid "'''" msgstr "'''" #. type: Plain text #: documentation/content/en/articles/pgpkeys/_index.adoc:50 msgid "" "These OpenPGP keys can be used to verify a signature or send encrypted email " "to `FreeBSD.org` officers or developers. The complete keyring can be " "downloaded at link:https://docs.FreeBSD.org/pgpkeys/pgpkeys.txt[pgpkeyring." "txt]." msgstr "" "Эти OpenPGP-ключи можно использовать для проверки подписи или отправки " "зашифрованной электронной почты офицерам или разработчикам `FreeBSD.org`. " "Полный набор ключей можно загрузить по ссылке link:https://docs.FreeBSD.org/" "pgpkeys/pgpkeys.txt[pgpkeyring.txt]." # # #. Do not edit this file except as instructed by the addkey.sh script. #. See the README file in /data/pgpkeys for instructions. #. This article contains all the keys. The officer keys are also #. shown in the Handbook PGP keys chapter. #. type: Title == #: documentation/content/en/articles/pgpkeys/_index.adoc:61 #, no-wrap msgid "Officers" msgstr "Офицеры" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:63 #, no-wrap msgid "{security-officer-name} `<{security-officer-email}>`" msgstr "{security-officer-name} `<{security-officer-email}>`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:66 #, no-wrap msgid "{core-secretary-name} `<{core-secretary-email}>`" msgstr "{core-secretary-name} `<{core-secretary-email}>`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:69 #, no-wrap msgid "{portmgr-secretary-name} `<{portmgr-secretary-email}>`" msgstr "{portmgr-secretary-name} `<{portmgr-secretary-email}>`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:72 #, no-wrap msgid "{doceng-secretary-name} `<{doceng-secretary-email}>`" msgstr "{doceng-secretary-name} `<{doceng-secretary-email}>`" #. type: Title == #: documentation/content/en/articles/pgpkeys/_index.adoc:76 #, no-wrap msgid "Core Team Members" msgstr "Участники Основной команды (Core Team)" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:78 -#: documentation/content/en/articles/pgpkeys/_index.adoc:648 +#: documentation/content/en/articles/pgpkeys/_index.adoc:651 #, no-wrap msgid "`{allanjude}`" msgstr "`{allanjude}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:81 -#: documentation/content/en/articles/pgpkeys/_index.adoc:339 +#: documentation/content/en/articles/pgpkeys/_index.adoc:342 #, no-wrap msgid "`{dch}`" msgstr "`{dch}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:84 -#: documentation/content/en/articles/pgpkeys/_index.adoc:1257 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1263 #, no-wrap msgid "`{glebius}`" msgstr "`{glebius}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:87 #, no-wrap msgid "`{hrs}`" msgstr "`{hrs}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:90 -#: documentation/content/en/articles/pgpkeys/_index.adoc:600 +#: documentation/content/en/articles/pgpkeys/_index.adoc:603 #, no-wrap msgid "`{lwhsu}`" msgstr "`{lwhsu}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:93 #: documentation/content/en/articles/pgpkeys/_index.adoc:147 #, no-wrap msgid "`{mat}`" msgstr "`{mat}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:96 -#: documentation/content/en/articles/pgpkeys/_index.adoc:336 +#: documentation/content/en/articles/pgpkeys/_index.adoc:339 #, no-wrap msgid "`{olivier}`" msgstr "`{olivier}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:99 #: documentation/content/en/articles/pgpkeys/_index.adoc:198 #, no-wrap msgid "`{tcberner}`" msgstr "`{tcberner}`" #. type: Title == #: documentation/content/en/articles/pgpkeys/_index.adoc:103 #, no-wrap msgid "Developers" msgstr "Разработчики" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:105 #, no-wrap msgid "`{jgh}`" msgstr "`{jgh}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:108 #, no-wrap msgid "`{ariff}`" msgstr "`{ariff}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:111 #, no-wrap msgid "`{tabthorpe}`" msgstr "`{tabthorpe}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:114 #, no-wrap msgid "`{eadler}`" msgstr "`{eadler}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:117 #, no-wrap msgid "`{pauamma}`" msgstr "`{pauamma}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:120 #, no-wrap msgid "`{shaun}`" msgstr "`{shaun}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:123 #, no-wrap msgid "`{brix}`" msgstr "`{brix}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:126 #, no-wrap msgid "`{mandree}`" msgstr "`{mandree}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:129 #, no-wrap msgid "`{will}`" msgstr "`{will}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:132 #, no-wrap msgid "`{dim}`" msgstr "`{dim}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:135 #, no-wrap msgid "`{anholt}`" msgstr "`{anholt}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:138 #, no-wrap msgid "`{fernape}`" msgstr "`{fernape}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:141 #, no-wrap msgid "`{mva}`" msgstr "`{mva}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:144 #, no-wrap msgid "`{araujo}`" msgstr "`{araujo}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:150 #, no-wrap msgid "`{syuu}`" msgstr "`{syuu}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:153 #, no-wrap msgid "`{asami}`" msgstr "`{asami}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:156 #, no-wrap msgid "`{jsa}`" msgstr "`{jsa}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:159 #, no-wrap msgid "`{jadawin}`" msgstr "`{jadawin}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:162 #, no-wrap msgid "`{jwb}`" msgstr "`{jwb}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:165 #, no-wrap msgid "`{dbaio}`" msgstr "`{dbaio}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:168 #, no-wrap msgid "`{timur}`" msgstr "`{timur}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:171 #, no-wrap msgid "`{jhb}`" msgstr "`{jhb}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:174 #, no-wrap msgid "`{gjb}`" msgstr "`{gjb}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:177 #, no-wrap msgid "`{snb}`" msgstr "`{snb}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:180 #, no-wrap msgid "`{barner}`" msgstr "`{barner}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:183 #, no-wrap msgid "`{lbartoletti}`" msgstr "`{lbartoletti}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:186 #, no-wrap msgid "`{art}`" msgstr "`{art}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:189 #, no-wrap msgid "`{tobez}`" msgstr "`{tobez}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:192 #, no-wrap msgid "`{damien}`" msgstr "`{damien}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:195 #, no-wrap msgid "`{bdragon}`" msgstr "`{bdragon}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:201 #, no-wrap msgid "`{tdb}`" msgstr "`{tdb}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:204 #, no-wrap msgid "`{mbr}`" msgstr "`{mbr}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:207 #, no-wrap msgid "`{bvs}`" msgstr "`{bvs}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:210 #, no-wrap msgid "`{jbo}`" msgstr "`{jbo}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:213 #, no-wrap msgid "`{novel}`" msgstr "`{novel}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:216 #, no-wrap msgid "`{garga}`" msgstr "`{garga}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:219 #, no-wrap msgid "`{kbowling}`" msgstr "`{kbowling}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:222 #, no-wrap msgid "`{alexbl}`" msgstr "`{alexbl}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:225 #, no-wrap msgid "`{ebrandi}`" msgstr "`{ebrandi}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:228 #, no-wrap msgid "`{harti}`" msgstr "`{harti}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:231 #, no-wrap msgid "`{obraun}`" msgstr "`{obraun}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:234 #, no-wrap msgid "`{makc}`" msgstr "`{makc}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:237 #, no-wrap msgid "`{jmb}`" msgstr "`{jmb}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:240 #, no-wrap msgid "`{dab}`" msgstr "`{dab}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:243 #, no-wrap msgid "`{antoine}`" msgstr "`{antoine}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:246 #, no-wrap msgid "`{db}`" msgstr "`{db}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:249 #, no-wrap msgid "`{brueffer}`" msgstr "`{brueffer}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:252 #, no-wrap msgid "`{markus}`" msgstr "`{markus}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:255 #, no-wrap msgid "`{br}`" msgstr "`{br}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:258 #, no-wrap msgid "`{jch}`" msgstr "`{jch}`" #. type: Title === #: documentation/content/en/articles/pgpkeys/_index.adoc:261 #, no-wrap +msgid "`{laurent}`" +msgstr "`{laurent}`" + +#. type: Title === +#: documentation/content/en/articles/pgpkeys/_index.adoc:264 +#, no-wrap msgid "`{jchandra}`" msgstr "`{jchandra}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:264 +#: documentation/content/en/articles/pgpkeys/_index.adoc:267 #, no-wrap msgid "`{jcamou}`" msgstr "`{jcamou}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:267 +#: documentation/content/en/articles/pgpkeys/_index.adoc:270 #, no-wrap msgid "`{acm}`" msgstr "`{acm}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:270 +#: documentation/content/en/articles/pgpkeys/_index.adoc:273 #, no-wrap msgid "`{olce}`" msgstr "`{olce}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:273 +#: documentation/content/en/articles/pgpkeys/_index.adoc:276 #, no-wrap msgid "`{gahr}`" msgstr "`{gahr}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:276 +#: documentation/content/en/articles/pgpkeys/_index.adoc:279 #, no-wrap msgid "`{dchagin}`" msgstr "`{dchagin}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:279 +#: documentation/content/en/articles/pgpkeys/_index.adoc:282 #, no-wrap msgid "`{perky}`" msgstr "`{perky}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:282 +#: documentation/content/en/articles/pgpkeys/_index.adoc:285 #, no-wrap msgid "`{jon}`" msgstr "`{jon}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:285 +#: documentation/content/en/articles/pgpkeys/_index.adoc:288 #, no-wrap msgid "`{jonathan}`" msgstr "`{jonathan}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:288 +#: documentation/content/en/articles/pgpkeys/_index.adoc:291 #, no-wrap msgid "`{loader}`" msgstr "`{loader}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:291 +#: documentation/content/en/articles/pgpkeys/_index.adoc:294 #, no-wrap msgid "`{luoqi}`" msgstr "`{luoqi}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:294 +#: documentation/content/en/articles/pgpkeys/_index.adoc:297 #, no-wrap msgid "`{ache}`" msgstr "`{ache}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:297 +#: documentation/content/en/articles/pgpkeys/_index.adoc:300 #, no-wrap msgid "`{melifaro}`" msgstr "`{melifaro}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:300 +#: documentation/content/en/articles/pgpkeys/_index.adoc:303 #, no-wrap msgid "`{cjh}`" msgstr "`{cjh}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:303 +#: documentation/content/en/articles/pgpkeys/_index.adoc:306 #, no-wrap msgid "`{davidch}`" msgstr "`{davidch}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:306 +#: documentation/content/en/articles/pgpkeys/_index.adoc:309 #, no-wrap msgid "`{milki}`" msgstr "`{milki}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:309 +#: documentation/content/en/articles/pgpkeys/_index.adoc:312 #, no-wrap msgid "`{cjc}`" msgstr "`{cjc}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:312 +#: documentation/content/en/articles/pgpkeys/_index.adoc:315 #, no-wrap msgid "`{marcus}`" msgstr "`{marcus}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:315 +#: documentation/content/en/articles/pgpkeys/_index.adoc:318 #, no-wrap msgid "`{fuz}`" msgstr "`{fuz}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:318 +#: documentation/content/en/articles/pgpkeys/_index.adoc:321 #, no-wrap msgid "`{nik}`" msgstr "`{nik}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:321 +#: documentation/content/en/articles/pgpkeys/_index.adoc:324 #, no-wrap msgid "`{benjsc}`" msgstr "`{benjsc}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:324 +#: documentation/content/en/articles/pgpkeys/_index.adoc:327 #, no-wrap msgid "`{lcook}`" msgstr "`{lcook}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:327 +#: documentation/content/en/articles/pgpkeys/_index.adoc:330 #, no-wrap msgid "`{ngie}`" msgstr "`{ngie}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:330 +#: documentation/content/en/articles/pgpkeys/_index.adoc:333 #, no-wrap msgid "`{rakuco}`" msgstr "`{rakuco}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:333 +#: documentation/content/en/articles/pgpkeys/_index.adoc:336 #, no-wrap msgid "`{alc}`" msgstr "`{alc}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:342 +#: documentation/content/en/articles/pgpkeys/_index.adoc:345 #, no-wrap msgid "`{bcran}`" msgstr "`{bcran}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:345 +#: documentation/content/en/articles/pgpkeys/_index.adoc:348 #, no-wrap msgid "`{cc}`" msgstr "`{cc}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:348 +#: documentation/content/en/articles/pgpkeys/_index.adoc:351 #, no-wrap msgid "`{culot}`" msgstr "`{culot}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:351 +#: documentation/content/en/articles/pgpkeys/_index.adoc:354 #, no-wrap msgid "`{alfredo}`" msgstr "`{alfredo}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:354 +#: documentation/content/en/articles/pgpkeys/_index.adoc:357 #, no-wrap msgid "`{bapt}`" msgstr "`{bapt}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:357 +#: documentation/content/en/articles/pgpkeys/_index.adoc:360 #, no-wrap msgid "`{ceri}`" msgstr "`{ceri}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:360 +#: documentation/content/en/articles/pgpkeys/_index.adoc:363 #, no-wrap msgid "`{edavis}`" msgstr "`{edavis}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:363 +#: documentation/content/en/articles/pgpkeys/_index.adoc:366 #, no-wrap msgid "`{alexey}`" msgstr "`{alexey}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:366 +#: documentation/content/en/articles/pgpkeys/_index.adoc:369 #, no-wrap msgid "`{bsd}`" msgstr "`{bsd}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:369 +#: documentation/content/en/articles/pgpkeys/_index.adoc:372 #, no-wrap msgid "`{carl}`" msgstr "`{carl}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:372 +#: documentation/content/en/articles/pgpkeys/_index.adoc:375 #, no-wrap msgid "`{carlavilla}`" msgstr "`{carlavilla}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:375 +#: documentation/content/en/articles/pgpkeys/_index.adoc:378 #, no-wrap msgid "`{vd}`" msgstr "`{vd}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:378 +#: documentation/content/en/articles/pgpkeys/_index.adoc:381 #, no-wrap msgid "`{rdivacky}`" msgstr "`{rdivacky}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:381 +#: documentation/content/en/articles/pgpkeys/_index.adoc:384 #, no-wrap msgid "`{danfe}`" msgstr "`{danfe}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:384 +#: documentation/content/en/articles/pgpkeys/_index.adoc:387 #, no-wrap msgid "`{dd}`" msgstr "`{dd}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:387 +#: documentation/content/en/articles/pgpkeys/_index.adoc:390 #, no-wrap msgid "`{bdrewery}`" msgstr "`{bdrewery}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:390 +#: documentation/content/en/articles/pgpkeys/_index.adoc:393 #, no-wrap msgid "`{gad}`" msgstr "`{gad}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:393 +#: documentation/content/en/articles/pgpkeys/_index.adoc:396 #, no-wrap msgid "`{kd}`" msgstr "`{kd}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:396 +#: documentation/content/en/articles/pgpkeys/_index.adoc:399 #, no-wrap msgid "`{olivierd}`" msgstr "`{olivierd}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:399 +#: documentation/content/en/articles/pgpkeys/_index.adoc:402 #, no-wrap msgid "`{bruno}`" msgstr "`{bruno}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:402 +#: documentation/content/en/articles/pgpkeys/_index.adoc:405 #, no-wrap msgid "`{ale}`" msgstr "`{ale}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:405 +#: documentation/content/en/articles/pgpkeys/_index.adoc:408 #, no-wrap msgid "`{jlduran}`" msgstr "`{jlduran}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:408 +#: documentation/content/en/articles/pgpkeys/_index.adoc:411 #, no-wrap msgid "`{nemysis}`" msgstr "`{nemysis}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:411 +#: documentation/content/en/articles/pgpkeys/_index.adoc:414 #, no-wrap msgid "`{peadar}`" msgstr "`{peadar}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:414 +#: documentation/content/en/articles/pgpkeys/_index.adoc:417 #, no-wrap msgid "`{deischen}`" msgstr "`{deischen}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:417 +#: documentation/content/en/articles/pgpkeys/_index.adoc:420 #, no-wrap msgid "`{diizzy}`" msgstr "`{diizzy}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:420 +#: documentation/content/en/articles/pgpkeys/_index.adoc:423 #, no-wrap msgid "`{ue}`" msgstr "`{ue}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:423 +#: documentation/content/en/articles/pgpkeys/_index.adoc:426 #, no-wrap msgid "`{madpilot}`" msgstr "`{madpilot}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:426 +#: documentation/content/en/articles/pgpkeys/_index.adoc:429 #, no-wrap msgid "`{rafan}`" msgstr "`{rafan}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:429 +#: documentation/content/en/articles/pgpkeys/_index.adoc:432 #, no-wrap msgid "`{kami}`" msgstr "`{kami}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:432 +#: documentation/content/en/articles/pgpkeys/_index.adoc:435 #, no-wrap msgid "`{farrokhi}`" msgstr "`{farrokhi}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:435 +#: documentation/content/en/articles/pgpkeys/_index.adoc:438 #, no-wrap msgid "`{jedgar}`" msgstr "`{jedgar}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:438 +#: documentation/content/en/articles/pgpkeys/_index.adoc:441 #, no-wrap msgid "`{mfechner}`" msgstr "`{mfechner}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:441 +#: documentation/content/en/articles/pgpkeys/_index.adoc:444 #, no-wrap msgid "`{feld}`" msgstr "`{feld}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:444 +#: documentation/content/en/articles/pgpkeys/_index.adoc:447 #, no-wrap msgid "`{green}`" msgstr "`{green}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:447 +#: documentation/content/en/articles/pgpkeys/_index.adoc:450 #, no-wrap msgid "`{fanf}`" msgstr "`{fanf}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:450 +#: documentation/content/en/articles/pgpkeys/_index.adoc:453 #, no-wrap msgid "`{blackend}`" msgstr "`{blackend}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:453 +#: documentation/content/en/articles/pgpkeys/_index.adoc:456 #, no-wrap msgid "`{petef}`" msgstr "`{petef}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:456 +#: documentation/content/en/articles/pgpkeys/_index.adoc:459 #, no-wrap msgid "`{decke}`" msgstr "`{decke}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:459 +#: documentation/content/en/articles/pgpkeys/_index.adoc:462 #, no-wrap msgid "`{landonf}`" msgstr "`{landonf}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:462 +#: documentation/content/en/articles/pgpkeys/_index.adoc:465 #, no-wrap msgid "`{billf}`" msgstr "`{billf}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:465 +#: documentation/content/en/articles/pgpkeys/_index.adoc:468 #, no-wrap msgid "`{grembo}`" msgstr "`{grembo}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:468 +#: documentation/content/en/articles/pgpkeys/_index.adoc:471 #, no-wrap msgid "`{sgalabov}`" msgstr "`{sgalabov}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:471 +#: documentation/content/en/articles/pgpkeys/_index.adoc:474 #, no-wrap msgid "`{kgalazka}`" msgstr "`{kgalazka}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:474 +#: documentation/content/en/articles/pgpkeys/_index.adoc:477 #, no-wrap msgid "`{avg}`" msgstr "`{avg}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:477 +#: documentation/content/en/articles/pgpkeys/_index.adoc:480 #, no-wrap msgid "`{tiga}`" msgstr "`{tiga}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:480 +#: documentation/content/en/articles/pgpkeys/_index.adoc:483 #, no-wrap msgid "`{beat}`" msgstr "`{beat}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:483 +#: documentation/content/en/articles/pgpkeys/_index.adoc:486 #, no-wrap msgid "`{sjg}`" msgstr "`{sjg}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:486 +#: documentation/content/en/articles/pgpkeys/_index.adoc:489 #, no-wrap msgid "`{gibbs}`" msgstr "`{gibbs}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:489 +#: documentation/content/en/articles/pgpkeys/_index.adoc:492 #, no-wrap msgid "`{pfg}`" msgstr "`{pfg}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:492 +#: documentation/content/en/articles/pgpkeys/_index.adoc:495 #, no-wrap msgid "`{girgen}`" msgstr "`{girgen}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:495 +#: documentation/content/en/articles/pgpkeys/_index.adoc:498 #, no-wrap msgid "`{eugen}`" msgstr "`{eugen}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:498 +#: documentation/content/en/articles/pgpkeys/_index.adoc:501 #, no-wrap msgid "`{pgollucci}`" msgstr "`{pgollucci}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:501 +#: documentation/content/en/articles/pgpkeys/_index.adoc:504 #, no-wrap msgid "`{trociny}`" msgstr "`{trociny}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:504 +#: documentation/content/en/articles/pgpkeys/_index.adoc:507 #, no-wrap msgid "`{dmgk}`" msgstr "`{dmgk}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:507 +#: documentation/content/en/articles/pgpkeys/_index.adoc:510 #, no-wrap msgid "`{daichi}`" msgstr "`{daichi}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:510 +#: documentation/content/en/articles/pgpkeys/_index.adoc:513 #, no-wrap msgid "`{grehan}`" msgstr "`{grehan}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:513 +#: documentation/content/en/articles/pgpkeys/_index.adoc:516 #, no-wrap msgid "`{jamie}`" msgstr "`{jamie}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:516 +#: documentation/content/en/articles/pgpkeys/_index.adoc:519 #, no-wrap msgid "`{adridg}`" msgstr "`{adridg}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:519 +#: documentation/content/en/articles/pgpkeys/_index.adoc:522 #, no-wrap msgid "`{wg}`" msgstr "`{wg}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:522 +#: documentation/content/en/articles/pgpkeys/_index.adoc:525 #, no-wrap msgid "`{bar}`" msgstr "`{bar}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:525 +#: documentation/content/en/articles/pgpkeys/_index.adoc:528 #, no-wrap msgid "`{jmg}`" msgstr "`{jmg}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:528 +#: documentation/content/en/articles/pgpkeys/_index.adoc:531 #, no-wrap msgid "`{mjg}`" msgstr "`{mjg}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:531 +#: documentation/content/en/articles/pgpkeys/_index.adoc:534 #, no-wrap msgid "`{jhale}`" msgstr "`{jhale}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:534 +#: documentation/content/en/articles/pgpkeys/_index.adoc:537 #, no-wrap msgid "`{jah}`" msgstr "`{jah}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:537 +#: documentation/content/en/articles/pgpkeys/_index.adoc:540 #, no-wrap msgid "`{dannyboy}`" msgstr "`{dannyboy}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:540 +#: documentation/content/en/articles/pgpkeys/_index.adoc:543 #, no-wrap msgid "`{dhartmei}`" msgstr "`{dhartmei}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:543 +#: documentation/content/en/articles/pgpkeys/_index.adoc:546 #, no-wrap msgid "`{ohauer}`" msgstr "`{ohauer}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:546 +#: documentation/content/en/articles/pgpkeys/_index.adoc:549 #, no-wrap msgid "`{ehaupt}`" msgstr "`{ehaupt}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:549 +#: documentation/content/en/articles/pgpkeys/_index.adoc:552 #, no-wrap msgid "`{jhay}`" msgstr "`{jhay}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:552 +#: documentation/content/en/articles/pgpkeys/_index.adoc:555 #, no-wrap msgid "`{bhd}`" msgstr "`{bhd}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:555 +#: documentation/content/en/articles/pgpkeys/_index.adoc:558 #, no-wrap msgid "`{sheldonh}`" msgstr "`{sheldonh}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:558 +#: documentation/content/en/articles/pgpkeys/_index.adoc:561 #, no-wrap msgid "`{mikeh}`" msgstr "`{mikeh}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:561 +#: documentation/content/en/articles/pgpkeys/_index.adoc:564 #, no-wrap msgid "`{mheinen}`" msgstr "`{mheinen}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:564 +#: documentation/content/en/articles/pgpkeys/_index.adoc:567 #, no-wrap msgid "`{niels}`" msgstr "`{niels}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:567 +#: documentation/content/en/articles/pgpkeys/_index.adoc:570 #, no-wrap msgid "`{ghelmer}`" msgstr "`{ghelmer}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:570 +#: documentation/content/en/articles/pgpkeys/_index.adoc:573 #, no-wrap msgid "`{mux}`" msgstr "`{mux}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:573 +#: documentation/content/en/articles/pgpkeys/_index.adoc:576 #, no-wrap msgid "`{wen}`" msgstr "`{wen}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:576 +#: documentation/content/en/articles/pgpkeys/_index.adoc:579 #, no-wrap msgid "`{dhn}`" msgstr "`{dhn}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:579 +#: documentation/content/en/articles/pgpkeys/_index.adoc:582 #, no-wrap msgid "`{jhibbits}`" msgstr "`{jhibbits}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:582 +#: documentation/content/en/articles/pgpkeys/_index.adoc:585 #, no-wrap msgid "`{jhixson}`" msgstr "`{jhixson}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:585 +#: documentation/content/en/articles/pgpkeys/_index.adoc:588 #, no-wrap msgid "`{pho}`" msgstr "`{pho}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:588 +#: documentation/content/en/articles/pgpkeys/_index.adoc:591 #, no-wrap msgid "`{oh}`" msgstr "`{oh}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:591 +#: documentation/content/en/articles/pgpkeys/_index.adoc:594 #, no-wrap msgid "`{mhorne}`" msgstr "`{mhorne}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:594 +#: documentation/content/en/articles/pgpkeys/_index.adoc:597 #, no-wrap msgid "`{bhughes}`" msgstr "`{bhughes}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:597 +#: documentation/content/en/articles/pgpkeys/_index.adoc:600 #, no-wrap msgid "`{sunpoet}`" msgstr "`{sunpoet}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:603 +#: documentation/content/en/articles/pgpkeys/_index.adoc:606 #, no-wrap msgid "`{foxfair}`" msgstr "`{foxfair}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:606 +#: documentation/content/en/articles/pgpkeys/_index.adoc:609 #, no-wrap msgid "`{whu}`" msgstr "`{whu}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:609 +#: documentation/content/en/articles/pgpkeys/_index.adoc:612 #, no-wrap msgid "`{chinsan}`" msgstr "`{chinsan}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:612 +#: documentation/content/en/articles/pgpkeys/_index.adoc:615 #, no-wrap msgid "`{zlei}`" msgstr "`{zlei}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:615 +#: documentation/content/en/articles/pgpkeys/_index.adoc:618 #, no-wrap msgid "`{davide}`" msgstr "`{davide}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:618 +#: documentation/content/en/articles/pgpkeys/_index.adoc:621 #, no-wrap msgid "`{jkh}`" msgstr "`{jkh}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:621 +#: documentation/content/en/articles/pgpkeys/_index.adoc:624 #, no-wrap msgid "`{versus}`" msgstr "`{versus}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:624 +#: documentation/content/en/articles/pgpkeys/_index.adoc:627 #, no-wrap msgid "`{pi}`" msgstr "`{pi}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:627 +#: documentation/content/en/articles/pgpkeys/_index.adoc:630 #, no-wrap msgid "`{weongyo}`" msgstr "`{weongyo}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:630 +#: documentation/content/en/articles/pgpkeys/_index.adoc:633 #, no-wrap msgid "`{peterj}`" msgstr "`{peterj}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:633 +#: documentation/content/en/articles/pgpkeys/_index.adoc:636 #, no-wrap msgid "`{jinmei}`" msgstr "`{jinmei}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:636 +#: documentation/content/en/articles/pgpkeys/_index.adoc:639 #, no-wrap msgid "`{ahze}`" msgstr "`{ahze}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:639 +#: documentation/content/en/articles/pgpkeys/_index.adoc:642 #, no-wrap msgid "`{markj}`" msgstr "`{markj}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:642 +#: documentation/content/en/articles/pgpkeys/_index.adoc:645 #, no-wrap msgid "`{trevor}`" msgstr "`{trevor}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:645 +#: documentation/content/en/articles/pgpkeys/_index.adoc:648 #, no-wrap msgid "`{erj}`" msgstr "`{erj}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:651 +#: documentation/content/en/articles/pgpkeys/_index.adoc:654 #, no-wrap msgid "`{bjk}`" msgstr "`{bjk}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:654 +#: documentation/content/en/articles/pgpkeys/_index.adoc:657 #, no-wrap msgid "`{phk}`" msgstr "`{phk}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:657 +#: documentation/content/en/articles/pgpkeys/_index.adoc:660 #, no-wrap msgid "`{pluknet}`" msgstr "`{pluknet}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:660 +#: documentation/content/en/articles/pgpkeys/_index.adoc:663 #, no-wrap msgid "`{cokane}`" msgstr "`{cokane}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:663 +#: documentation/content/en/articles/pgpkeys/_index.adoc:666 +#, no-wrap +msgid "`{mce}`" +msgstr "`{mce}`" + +#. type: Title === +#: documentation/content/en/articles/pgpkeys/_index.adoc:669 #, no-wrap msgid "`{karels}`" msgstr "`{karels}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:666 +#: documentation/content/en/articles/pgpkeys/_index.adoc:672 #, no-wrap msgid "`{kato}`" msgstr "`{kato}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:669 +#: documentation/content/en/articles/pgpkeys/_index.adoc:675 #, no-wrap msgid "`{vkashyap}`" msgstr "`{vkashyap}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:672 +#: documentation/content/en/articles/pgpkeys/_index.adoc:678 #, no-wrap msgid "`{pkubaj}`" msgstr "`{pkubaj}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:675 +#: documentation/content/en/articles/pgpkeys/_index.adoc:681 #, no-wrap msgid "`{kris}`" msgstr "`{kris}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:678 +#: documentation/content/en/articles/pgpkeys/_index.adoc:684 #, no-wrap msgid "`{keramida}`" msgstr "`{keramida}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:681 +#: documentation/content/en/articles/pgpkeys/_index.adoc:687 #, no-wrap msgid "`{fjoe}`" msgstr "`{fjoe}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:684 +#: documentation/content/en/articles/pgpkeys/_index.adoc:690 #, no-wrap msgid "`{manolis}`" msgstr "`{manolis}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:687 +#: documentation/content/en/articles/pgpkeys/_index.adoc:693 #, no-wrap msgid "`{stevek}`" msgstr "`{stevek}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:690 +#: documentation/content/en/articles/pgpkeys/_index.adoc:696 #, no-wrap msgid "`{jkim}`" msgstr "`{jkim}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:693 +#: documentation/content/en/articles/pgpkeys/_index.adoc:699 #, no-wrap msgid "`{zack}`" msgstr "`{zack}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:696 +#: documentation/content/en/articles/pgpkeys/_index.adoc:702 #, no-wrap msgid "`{akiyano}`" msgstr "`{akiyano}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:699 +#: documentation/content/en/articles/pgpkeys/_index.adoc:705 #, no-wrap msgid "`{jceel}`" msgstr "`{jceel}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:702 +#: documentation/content/en/articles/pgpkeys/_index.adoc:708 #, no-wrap msgid "`{andreas}`" msgstr "`{andreas}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:705 +#: documentation/content/en/articles/pgpkeys/_index.adoc:711 #, no-wrap msgid "`{kai}`" msgstr "`{kai}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:708 +#: documentation/content/en/articles/pgpkeys/_index.adoc:714 #, no-wrap msgid "`{corvink}`" msgstr "`{corvink}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:711 +#: documentation/content/en/articles/pgpkeys/_index.adoc:717 #, no-wrap msgid "`{jkois}`" msgstr "`{jkois}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:714 +#: documentation/content/en/articles/pgpkeys/_index.adoc:720 #, no-wrap msgid "`{sergei}`" msgstr "`{sergei}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:717 +#: documentation/content/en/articles/pgpkeys/_index.adoc:723 #, no-wrap msgid "`{maxim}`" msgstr "`{maxim}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:720 +#: documentation/content/en/articles/pgpkeys/_index.adoc:726 #, no-wrap msgid "`{taras}`" msgstr "`{taras}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:723 +#: documentation/content/en/articles/pgpkeys/_index.adoc:729 #, no-wrap msgid "`{tobik}`" msgstr "`{tobik}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:726 +#: documentation/content/en/articles/pgpkeys/_index.adoc:732 #, no-wrap msgid "`{jkoshy}`" msgstr "`{jkoshy}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:729 +#: documentation/content/en/articles/pgpkeys/_index.adoc:735 #, no-wrap msgid "`{wkoszek}`" msgstr "`{wkoszek}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:732 +#: documentation/content/en/articles/pgpkeys/_index.adoc:738 #, no-wrap msgid "`{ak}`" msgstr "`{ak}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:735 +#: documentation/content/en/articles/pgpkeys/_index.adoc:741 #, no-wrap msgid "`{gabor}`" msgstr "`{gabor}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:738 +#: documentation/content/en/articles/pgpkeys/_index.adoc:744 #, no-wrap msgid "`{anchie}`" msgstr "`{anchie}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:741 +#: documentation/content/en/articles/pgpkeys/_index.adoc:747 #, no-wrap msgid "`{rushani}`" msgstr "`{rushani}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:744 +#: documentation/content/en/articles/pgpkeys/_index.adoc:750 #, no-wrap msgid "`{kuriyama}`" msgstr "`{kuriyama}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:747 +#: documentation/content/en/articles/pgpkeys/_index.adoc:753 #, no-wrap msgid "`{rene}`" msgstr "`{rene}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:750 +#: documentation/content/en/articles/pgpkeys/_index.adoc:756 #, no-wrap msgid "`{jlaffaye}`" msgstr "`{jlaffaye}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:753 +#: documentation/content/en/articles/pgpkeys/_index.adoc:759 #, no-wrap msgid "`{clement}`" msgstr "`{clement}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:756 +#: documentation/content/en/articles/pgpkeys/_index.adoc:762 #, no-wrap msgid "`{mlaier}`" msgstr "`{mlaier}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:759 +#: documentation/content/en/articles/pgpkeys/_index.adoc:765 #, no-wrap msgid "`{martymac}`" msgstr "`{martymac}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:762 +#: documentation/content/en/articles/pgpkeys/_index.adoc:768 #, no-wrap msgid "`{glarkin}`" msgstr "`{glarkin}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:765 +#: documentation/content/en/articles/pgpkeys/_index.adoc:771 #, no-wrap msgid "`{dru}`" msgstr "`{dru}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:768 +#: documentation/content/en/articles/pgpkeys/_index.adoc:774 #, no-wrap msgid "`{lawrance}`" msgstr "`{lawrance}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:771 +#: documentation/content/en/articles/pgpkeys/_index.adoc:777 #, no-wrap msgid "`{njl}`" msgstr "`{njl}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:774 +#: documentation/content/en/articles/pgpkeys/_index.adoc:780 #, no-wrap msgid "`{jlh}`" msgstr "`{jlh}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:777 +#: documentation/content/en/articles/pgpkeys/_index.adoc:783 #, no-wrap msgid "`{leeym}`" msgstr "`{leeym}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:780 +#: documentation/content/en/articles/pgpkeys/_index.adoc:786 #, no-wrap msgid "`{sam}`" msgstr "`{sam}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:783 +#: documentation/content/en/articles/pgpkeys/_index.adoc:789 #, no-wrap msgid "`{jylefort}`" msgstr "`{jylefort}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:786 +#: documentation/content/en/articles/pgpkeys/_index.adoc:792 #, no-wrap msgid "`{grog}`" msgstr "`{grog}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:789 +#: documentation/content/en/articles/pgpkeys/_index.adoc:795 #, no-wrap msgid "`{oliver}`" msgstr "`{oliver}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:792 +#: documentation/content/en/articles/pgpkeys/_index.adoc:798 #, no-wrap msgid "`{netchild}`" msgstr "`{netchild}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:795 +#: documentation/content/en/articles/pgpkeys/_index.adoc:801 #, no-wrap msgid "`{leitao}`" msgstr "`{leitao}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:798 +#: documentation/content/en/articles/pgpkeys/_index.adoc:804 #, no-wrap msgid "`{ae}`" msgstr "`{ae}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:801 +#: documentation/content/en/articles/pgpkeys/_index.adoc:807 #, no-wrap msgid "`{lesi}`" msgstr "`{lesi}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:804 +#: documentation/content/en/articles/pgpkeys/_index.adoc:810 #, no-wrap msgid "`{achim}`" msgstr "`{achim}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:807 +#: documentation/content/en/articles/pgpkeys/_index.adoc:813 #, no-wrap msgid "`{cel}`" msgstr "`{cel}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:810 +#: documentation/content/en/articles/pgpkeys/_index.adoc:816 #, no-wrap msgid "`{glewis}`" msgstr "`{glewis}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:813 +#: documentation/content/en/articles/pgpkeys/_index.adoc:819 #, no-wrap msgid "`{vishwin}`" msgstr "`{vishwin}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:816 +#: documentation/content/en/articles/pgpkeys/_index.adoc:822 #, no-wrap msgid "`{delphij}`" msgstr "`{delphij}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:819 +#: documentation/content/en/articles/pgpkeys/_index.adoc:825 #, no-wrap msgid "`{avatar}`" msgstr "`{avatar}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:822 +#: documentation/content/en/articles/pgpkeys/_index.adoc:828 #, no-wrap msgid "`{ijliao}`" msgstr "`{ijliao}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:825 +#: documentation/content/en/articles/pgpkeys/_index.adoc:831 #, no-wrap msgid "`{rlibby}`" msgstr "`{rlibby}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:828 +#: documentation/content/en/articles/pgpkeys/_index.adoc:834 #, no-wrap msgid "`{pclin}`" msgstr "`{pclin}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:831 +#: documentation/content/en/articles/pgpkeys/_index.adoc:837 #, no-wrap msgid "`{yzlin}`" msgstr "`{yzlin}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:834 +#: documentation/content/en/articles/pgpkeys/_index.adoc:840 #, no-wrap msgid "`{linimon}`" msgstr "`{linimon}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:837 +#: documentation/content/en/articles/pgpkeys/_index.adoc:843 #, no-wrap msgid "`{arved}`" msgstr "`{arved}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:840 +#: documentation/content/en/articles/pgpkeys/_index.adoc:846 #, no-wrap msgid "`{dryice}`" msgstr "`{dryice}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:843 +#: documentation/content/en/articles/pgpkeys/_index.adoc:849 #, no-wrap msgid "`{nemoliu}`" msgstr "`{nemoliu}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:846 +#: documentation/content/en/articles/pgpkeys/_index.adoc:852 #, no-wrap msgid "`{kevlo}`" msgstr "`{kevlo}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:849 +#: documentation/content/en/articles/pgpkeys/_index.adoc:855 #, no-wrap msgid "`{zml}`" msgstr "`{zml}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:852 +#: documentation/content/en/articles/pgpkeys/_index.adoc:858 #, no-wrap msgid "`{nox}`" msgstr "`{nox}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:855 +#: documentation/content/en/articles/pgpkeys/_index.adoc:861 #, no-wrap msgid "`{avl}`" msgstr "`{avl}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:858 +#: documentation/content/en/articles/pgpkeys/_index.adoc:864 #, no-wrap msgid "`{scottl}`" msgstr "`{scottl}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:861 +#: documentation/content/en/articles/pgpkeys/_index.adoc:867 #, no-wrap msgid "`{rmacklem}`" msgstr "`{rmacklem}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:864 +#: documentation/content/en/articles/pgpkeys/_index.adoc:870 #, no-wrap msgid "`{vmaffione}`" msgstr "`{vmaffione}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:867 +#: documentation/content/en/articles/pgpkeys/_index.adoc:873 #, no-wrap msgid "`{bmah}`" msgstr "`{bmah}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:870 +#: documentation/content/en/articles/pgpkeys/_index.adoc:876 #, no-wrap msgid "`{rm}`" msgstr "`{rm}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:873 +#: documentation/content/en/articles/pgpkeys/_index.adoc:879 #, no-wrap msgid "`{mtm}`" msgstr "`{mtm}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:876 +#: documentation/content/en/articles/pgpkeys/_index.adoc:882 #, no-wrap msgid "`{dwmalone}`" msgstr "`{dwmalone}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:879 +#: documentation/content/en/articles/pgpkeys/_index.adoc:885 #, no-wrap msgid "`{christos}`" msgstr "`{christos}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:882 +#: documentation/content/en/articles/pgpkeys/_index.adoc:888 #, no-wrap msgid "`{marino}`" msgstr "`{marino}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:885 +#: documentation/content/en/articles/pgpkeys/_index.adoc:891 #, no-wrap msgid "`{emaste}`" msgstr "`{emaste}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:888 +#: documentation/content/en/articles/pgpkeys/_index.adoc:894 #, no-wrap msgid "`{cherry}`" msgstr "`{cherry}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:891 +#: documentation/content/en/articles/pgpkeys/_index.adoc:897 #, no-wrap msgid "`{matusita}`" msgstr "`{matusita}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:894 +#: documentation/content/en/articles/pgpkeys/_index.adoc:900 #, no-wrap msgid "`{mm}`" msgstr "`{mm}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:897 +#: documentation/content/en/articles/pgpkeys/_index.adoc:903 #, no-wrap msgid "`{sem}`" msgstr "`{sem}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:900 +#: documentation/content/en/articles/pgpkeys/_index.adoc:906 #, no-wrap msgid "`{rcm}`" msgstr "`{rcm}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:903 +#: documentation/content/en/articles/pgpkeys/_index.adoc:909 #, no-wrap msgid "`{mckusick}`" msgstr "`{mckusick}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:906 +#: documentation/content/en/articles/pgpkeys/_index.adoc:912 #, no-wrap msgid "`{tmclaugh}`" msgstr "`{tmclaugh}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:909 +#: documentation/content/en/articles/pgpkeys/_index.adoc:915 #, no-wrap msgid "`{jmelo}`" msgstr "`{jmelo}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:912 +#: documentation/content/en/articles/pgpkeys/_index.adoc:918 #, no-wrap msgid "`{mmel}`" msgstr "`{mmel}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:915 +#: documentation/content/en/articles/pgpkeys/_index.adoc:921 #, no-wrap msgid "`{jmmv}`" msgstr "`{jmmv}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:918 +#: documentation/content/en/articles/pgpkeys/_index.adoc:924 #, no-wrap msgid "`{kadesai}`" msgstr "`{kadesai}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:921 +#: documentation/content/en/articles/pgpkeys/_index.adoc:927 #, no-wrap msgid "`{ken}`" msgstr "`{ken}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:924 +#: documentation/content/en/articles/pgpkeys/_index.adoc:930 #, no-wrap msgid "`{markm}`" msgstr "`{markm}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:927 +#: documentation/content/en/articles/pgpkeys/_index.adoc:933 #, no-wrap msgid "`{dinoex}`" msgstr "`{dinoex}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:930 +#: documentation/content/en/articles/pgpkeys/_index.adoc:936 #, no-wrap msgid "`{sanpei}`" msgstr "`{sanpei}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:933 +#: documentation/content/en/articles/pgpkeys/_index.adoc:939 #, no-wrap msgid "`{rmh}`" msgstr "`{rmh}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:936 +#: documentation/content/en/articles/pgpkeys/_index.adoc:942 #, no-wrap msgid "`{driesm}`" msgstr "`{driesm}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:939 +#: documentation/content/en/articles/pgpkeys/_index.adoc:945 #, no-wrap msgid "`{jrm}`" msgstr "`{jrm}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:942 +#: documentation/content/en/articles/pgpkeys/_index.adoc:948 #, no-wrap msgid "`{freqlabs}`" msgstr "`{freqlabs}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:945 +#: documentation/content/en/articles/pgpkeys/_index.adoc:951 #, no-wrap msgid "`{mmoll}`" msgstr "`{mmoll}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:948 +#: documentation/content/en/articles/pgpkeys/_index.adoc:954 #, no-wrap msgid "`{cmt}`" msgstr "`{cmt}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:951 +#: documentation/content/en/articles/pgpkeys/_index.adoc:957 #, no-wrap msgid "`{stephen}`" msgstr "`{stephen}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:954 +#: documentation/content/en/articles/pgpkeys/_index.adoc:960 #, no-wrap msgid "`{marcel}`" msgstr "`{marcel}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:957 +#: documentation/content/en/articles/pgpkeys/_index.adoc:963 #, no-wrap msgid "`{dougm}`" msgstr "`{dougm}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:960 +#: documentation/content/en/articles/pgpkeys/_index.adoc:966 #, no-wrap msgid "`{kmoore}`" msgstr "`{kmoore}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:963 +#: documentation/content/en/articles/pgpkeys/_index.adoc:969 #, no-wrap msgid "`{marck}`" msgstr "`{marck}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:966 +#: documentation/content/en/articles/pgpkeys/_index.adoc:972 #, no-wrap msgid "`{mav}`" msgstr "`{mav}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:969 +#: documentation/content/en/articles/pgpkeys/_index.adoc:975 #, no-wrap msgid "`{rich}`" msgstr "`{rich}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:972 +#: documentation/content/en/articles/pgpkeys/_index.adoc:978 #, no-wrap msgid "`{knu}`" msgstr "`{knu}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:975 +#: documentation/content/en/articles/pgpkeys/_index.adoc:981 #, no-wrap msgid "`{tmm}`" msgstr "`{tmm}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:978 +#: documentation/content/en/articles/pgpkeys/_index.adoc:984 #, no-wrap msgid "`{max}`" msgstr "`{max}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:981 +#: documentation/content/en/articles/pgpkeys/_index.adoc:987 #, no-wrap msgid "`{maho}`" msgstr "`{maho}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:984 +#: documentation/content/en/articles/pgpkeys/_index.adoc:990 #, no-wrap msgid "`{yoichi}`" msgstr "`{yoichi}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:987 +#: documentation/content/en/articles/pgpkeys/_index.adoc:993 #, no-wrap msgid "`{bland}`" msgstr "`{bland}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:990 +#: documentation/content/en/articles/pgpkeys/_index.adoc:996 #, no-wrap msgid "`{gnn}`" msgstr "`{gnn}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:993 +#: documentation/content/en/articles/pgpkeys/_index.adoc:999 #, no-wrap msgid "`{khng}`" msgstr "`{khng}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:996 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1002 #, no-wrap msgid "`{simon}`" msgstr "`{simon}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:999 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1005 #, no-wrap msgid "`{rnoland}`" msgstr "`{rnoland}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1002 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1008 #, no-wrap msgid "`{anders}`" msgstr "`{anders}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1005 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1011 #, no-wrap msgid "`{lofi}`" msgstr "`{lofi}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1008 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1014 #, no-wrap msgid "`{obrien}`" msgstr "`{obrien}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1011 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1017 #, no-wrap msgid "`{olgeni}`" msgstr "`{olgeni}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1014 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1020 #, no-wrap msgid "`{philip}`" msgstr "`{philip}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1017 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1023 #, no-wrap msgid "`{jpaetzel}`" msgstr "`{jpaetzel}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1020 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1026 #, no-wrap msgid "`{zirias}`" msgstr "`{zirias}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1023 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1029 #, no-wrap msgid "`{hiren}`" msgstr "`{hiren}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1026 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1032 #, no-wrap msgid "`{hmp}`" msgstr "`{hmp}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1029 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1035 #, no-wrap msgid "`{fluffy}`" msgstr "`{fluffy}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1032 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1038 #, no-wrap msgid "`{sat}`" msgstr "`{sat}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1035 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1041 #, no-wrap msgid "`{np}`" msgstr "`{np}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1038 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1044 #, no-wrap msgid "`{royger}`" msgstr "`{royger}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1041 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1047 #, no-wrap msgid "`{rpaulo}`" msgstr "`{rpaulo}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1044 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1050 #, no-wrap msgid "`{misha}`" msgstr "`{misha}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1047 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1053 #, no-wrap msgid "`{dumbbell}`" msgstr "`{dumbbell}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1050 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1056 #, no-wrap msgid "`{rpokala}`" msgstr "`{rpokala}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1053 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1059 #, no-wrap msgid "`{mp}`" msgstr "`{mp}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1056 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1062 #, no-wrap msgid "`{roam}`" msgstr "`{roam}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1059 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1065 #, no-wrap msgid "`{den}`" msgstr "`{den}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1062 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1068 #, no-wrap msgid "`{csjp}`" msgstr "`{csjp}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1065 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1071 #, no-wrap msgid "`{grahamperrin}`" msgstr "`{grahamperrin}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1068 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1074 #, no-wrap msgid "`{gerald}`" msgstr "`{gerald}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1071 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1077 #, no-wrap msgid "`{scottph}`" msgstr "`{scottph}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1074 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1080 #, no-wrap msgid "`{jacula}`" msgstr "`{jacula}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1077 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1083 #, no-wrap msgid "`{0mp}`" msgstr "`{0mp}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1080 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1086 #, no-wrap msgid "`{jdp}`" msgstr "`{jdp}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1083 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1089 #, no-wrap msgid "`{krion}`" msgstr "`{krion}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1086 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1092 #, no-wrap msgid "`{vladlen}`" msgstr "`{vladlen}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1089 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1095 #, no-wrap msgid "`{sepotvin}`" msgstr "`{sepotvin}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1092 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1098 #, no-wrap msgid "`{cpm}`" msgstr "`{cpm}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1095 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1101 #, no-wrap msgid "`{markp}`" msgstr "`{markp}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1098 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1104 #, no-wrap msgid "`{alepulver}`" msgstr "`{alepulver}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1101 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1107 #, no-wrap msgid "`{kp}`" msgstr "`{kp}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1104 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1110 #, no-wrap msgid "`{thomas}`" msgstr "`{thomas}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1107 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1113 #, no-wrap msgid "`{hq}`" msgstr "`{hq}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1110 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1116 #, no-wrap msgid "`{bofh}`" msgstr "`{bofh}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1113 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1119 #, no-wrap msgid "`{fox}`" msgstr "`{fox}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1116 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1122 #, no-wrap msgid "`{lbr}`" msgstr "`{lbr}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1119 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1125 #, no-wrap msgid "`{crees}`" msgstr "`{crees}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1122 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1128 #, no-wrap msgid "`{rees}`" msgstr "`{rees}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1125 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1131 #, no-wrap msgid "`{mr}`" msgstr "`{mr}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1128 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1134 #, no-wrap msgid "`{bcr}`" msgstr "`{bcr}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1131 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1137 #, no-wrap msgid "`{trhodes}`" msgstr "`{trhodes}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1134 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1140 #, no-wrap msgid "`{benno}`" msgstr "`{benno}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1137 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1143 #, no-wrap msgid "`{beech}`" msgstr "`{beech}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1140 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1146 #, no-wrap msgid "`{roberto}`" msgstr "`{roberto}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1143 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1149 #, no-wrap msgid "`{rodrigc}`" msgstr "`{rodrigc}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1146 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1152 #, no-wrap msgid "`{michaelo}`" msgstr "`{michaelo}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1149 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1155 #, no-wrap msgid "`{igoro}`" msgstr "`{igoro}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1152 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1158 #, no-wrap msgid "`{dtxdf}`" msgstr "`{dtxdf}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1155 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1161 #, no-wrap msgid "`{ler}`" msgstr "`{ler}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1158 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1164 #, no-wrap msgid "`{leres}`" msgstr "`{leres}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1161 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1167 #, no-wrap msgid "`{robak}`" msgstr "`{robak}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1164 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1170 #, no-wrap msgid "`{guido}`" msgstr "`{guido}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1167 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1173 #, no-wrap msgid "`{rea}`" msgstr "`{rea}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1170 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1176 #, no-wrap msgid "`{ray}`" msgstr "`{ray}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1173 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1179 #, no-wrap msgid "`{niklas}`" msgstr "`{niklas}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1176 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1182 #, no-wrap msgid "`{salvadore}`" msgstr "`{salvadore}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1179 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1185 #, no-wrap msgid "`{bsam}`" msgstr "`{bsam}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1182 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1188 #, no-wrap msgid "`{marks}`" msgstr "`{marks}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1185 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1191 #, no-wrap msgid "`{bschmidt}`" msgstr "`{bschmidt}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1188 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1194 #, no-wrap msgid "`{wosch}`" msgstr "`{wosch}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1191 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1197 #, no-wrap msgid "`{cy}`" msgstr "`{cy}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1194 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1200 #, no-wrap msgid "`{das}`" msgstr "`{das}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1197 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1203 #, no-wrap msgid "`{scheidell}`" msgstr "`{scheidell}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1200 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1206 #, no-wrap msgid "`{matthew}`" msgstr "`{matthew}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1203 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1209 #, no-wrap msgid "`{tmseck}`" msgstr "`{tmseck}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1206 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1212 #, no-wrap msgid "`{johans}`" msgstr "`{johans}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1209 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1215 #, no-wrap msgid "`{bakul}`" msgstr "`{bakul}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1212 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1218 #, no-wrap msgid "`{gshapiro}`" msgstr "`{gshapiro}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1215 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1221 #, no-wrap msgid "`{wxs}`" msgstr "`{wxs}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1218 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1224 #, no-wrap msgid "`{nork}`" msgstr "`{nork}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1221 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1227 #, no-wrap msgid "`{syrinx}`" msgstr "`{syrinx}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1224 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1230 #, no-wrap msgid "`{vanilla}`" msgstr "`{vanilla}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1227 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1233 #, no-wrap msgid "`{ashafer}`" msgstr "`{ashafer}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1230 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1236 #, no-wrap msgid "`{ashish}`" msgstr "`{ashish}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1233 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1239 #, no-wrap msgid "`{asiciliano}`" msgstr "`{asiciliano}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1236 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1242 #, no-wrap msgid "`{chs}`" msgstr "`{chs}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1239 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1245 #, no-wrap msgid "`{bms}`" msgstr "`{bms}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1242 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1248 #, no-wrap msgid "`{demon}`" msgstr "`{demon}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1245 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1251 #, no-wrap msgid "`{jesper}`" msgstr "`{jesper}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1248 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1254 #, no-wrap msgid "`{scop}`" msgstr "`{scop}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1251 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1257 #, no-wrap msgid "`{anray}`" msgstr "`{anray}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1254 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1260 #, no-wrap msgid "`{flo}`" msgstr "`{flo}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1260 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1266 #, no-wrap msgid "`{kensmith}`" msgstr "`{kensmith}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1263 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1269 #, no-wrap msgid "`{ben}`" msgstr "`{ben}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1266 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1272 #, no-wrap msgid "`{des}`" msgstr "`{des}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1269 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1275 #, no-wrap msgid "`{sobomax}`" msgstr "`{sobomax}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1272 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1278 #, no-wrap msgid "`{asomers}`" msgstr "`{asomers}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1275 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1281 #, no-wrap msgid "`{brian}`" msgstr "`{brian}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1278 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1284 #, no-wrap msgid "`{sson}`" msgstr "`{sson}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1281 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1287 #, no-wrap msgid "`{nsouch}`" msgstr "`{nsouch}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1284 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1290 #, no-wrap msgid "`{ssouhlal}`" msgstr "`{ssouhlal}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1287 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1293 #, no-wrap msgid "`{loos}`" msgstr "`{loos}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1290 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1296 #, no-wrap msgid "`{brnrd}`" msgstr "`{brnrd}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1293 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1299 #, no-wrap msgid "`{rink}`" msgstr "`{rink}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1296 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1302 #, no-wrap msgid "`{vsevolod}`" msgstr "`{vsevolod}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1299 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1305 #, no-wrap msgid "`{pstef}`" msgstr "`{pstef}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1302 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1308 #, no-wrap msgid "`{zi}`" msgstr "`{zi}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1305 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1311 #, no-wrap msgid "`{lstewart}`" msgstr "`{lstewart}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1308 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1314 #, no-wrap msgid "`{murray}`" msgstr "`{murray}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1311 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1317 #, no-wrap msgid "`{vs}`" msgstr "`{vs}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1314 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1320 #, no-wrap msgid "`{xride}`" msgstr "`{xride}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1317 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1323 #, no-wrap msgid "`{marius}`" msgstr "`{marius}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1320 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1326 #, no-wrap msgid "`{cs}`" msgstr "`{cs}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1323 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1329 #, no-wrap msgid "`{clsung}`" msgstr "`{clsung}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1326 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1332 #, no-wrap msgid "`{gsutter}`" msgstr "`{gsutter}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1329 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1335 #, no-wrap msgid "`{metal}`" msgstr "`{metal}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1332 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1338 #, no-wrap msgid "`{ryusuke}`" msgstr "`{ryusuke}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1335 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1341 #, no-wrap msgid "`{nyan}`" msgstr "`{nyan}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1338 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1344 #, no-wrap msgid "`{sahil}`" msgstr "`{sahil}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1341 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1347 #, no-wrap msgid "`{tota}`" msgstr "`{tota}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1344 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1350 #, no-wrap msgid "`{romain}`" msgstr "`{romain}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1347 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1353 #, no-wrap msgid "`{eduardo}`" msgstr "`{eduardo}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1350 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1356 #, no-wrap msgid "`{sylvio}`" msgstr "`{sylvio}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1353 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1359 #, no-wrap msgid "`{itetcu}`" msgstr "`{itetcu}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1356 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1362 #, no-wrap msgid "`{mi}`" msgstr "`{mi}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1359 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1365 #, no-wrap msgid "`{gordon}`" msgstr "`{gordon}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1362 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1368 #, no-wrap msgid "`{lth}`" msgstr "`{lth}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1365 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1371 #, no-wrap msgid "`{fabient}`" msgstr "`{fabient}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1368 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1374 #, no-wrap msgid "`{thierry}`" msgstr "`{thierry}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1371 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1377 #, no-wrap msgid "`{thompsa}`" msgstr "`{thompsa}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1374 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1380 #, no-wrap msgid "`{flz}`" msgstr "`{flz}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1377 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1383 #, no-wrap msgid "`{jilles}`" msgstr "`{jilles}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1380 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1386 #, no-wrap msgid "`{ganbold}`" msgstr "`{ganbold}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1383 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1389 #, no-wrap msgid "`{tuexen}`" msgstr "`{tuexen}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1386 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1392 #, no-wrap msgid "`{gonzo}`" msgstr "`{gonzo}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1389 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1395 #, no-wrap msgid "`{uzsolt}`" msgstr "`{uzsolt}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1392 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1398 #, no-wrap msgid "`{ume}`" msgstr "`{ume}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1395 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1401 #, no-wrap msgid "`{ups}`" msgstr "`{ups}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1398 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1404 #, no-wrap msgid "`{fsu}`" msgstr "`{fsu}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1401 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1407 #, no-wrap msgid "`{mikael}`" msgstr "`{mikael}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1404 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1410 #, no-wrap msgid "`{manu}`" msgstr "`{manu}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1407 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1413 #, no-wrap msgid "`{ram}`" msgstr "`{ram}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1410 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1416 #, no-wrap msgid "`{bryanv}`" msgstr "`{bryanv}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1413 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1419 #, no-wrap msgid "`{nectar}`" msgstr "`{nectar}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1416 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1422 #, no-wrap msgid "`{avilla}`" msgstr "`{avilla}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1419 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1425 #, no-wrap msgid "`{nivit}`" msgstr "`{nivit}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1422 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1428 #, no-wrap msgid "`{ivoras}`" msgstr "`{ivoras}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1425 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1431 #, no-wrap msgid "`{stefan}`" msgstr "`{stefan}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1428 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1434 #, no-wrap msgid "`{kaiw}`" msgstr "`{kaiw}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1431 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1437 #, no-wrap msgid "`{adamw}`" msgstr "`{adamw}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1434 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1440 #, no-wrap msgid "`{naddy}`" msgstr "`{naddy}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1437 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1443 #, no-wrap msgid "`{peter}`" msgstr "`{peter}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1440 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1446 #, no-wrap msgid "`{nwhitehorn}`" msgstr "`{nwhitehorn}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1443 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1449 #, no-wrap msgid "`{obiwac}`" msgstr "`{obiwac}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1446 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1452 #, no-wrap msgid "`{miwi}`" msgstr "`{miwi}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1449 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1455 #, no-wrap msgid "`{nate}`" msgstr "`{nate}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1452 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1458 #, no-wrap msgid "`{twinterg}`" msgstr "`{twinterg}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1455 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1461 #, no-wrap msgid "`{def}`" msgstr "`{def}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1458 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1464 #, no-wrap msgid "`{wollman}`" msgstr "`{wollman}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1461 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1467 #, no-wrap msgid "`{joerg}`" msgstr "`{joerg}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1464 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1470 #, no-wrap msgid "`{ygy}`" msgstr "`{ygy}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1467 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1473 #, no-wrap msgid "`{emax}`" msgstr "`{emax}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1470 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1476 #, no-wrap msgid "`{oshogbo}`" msgstr "`{oshogbo}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1473 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1479 #, no-wrap msgid "`{andy}`" msgstr "`{andy}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1476 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1482 #, no-wrap msgid "`{riggs}`" msgstr "`{riggs}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1479 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1485 #, no-wrap msgid "`{egypcio}`" msgstr "`{egypcio}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1482 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1488 #, no-wrap msgid "`{bz}`" msgstr "`{bz}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1485 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1491 #, no-wrap msgid "`{dsl}`" msgstr "`{dsl}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1488 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1494 #, no-wrap msgid "`{zeising}`" msgstr "`{zeising}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1491 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1497 #, no-wrap msgid "`{phantom}`" msgstr "`{phantom}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1494 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1500 #, no-wrap msgid "`{tz}`" msgstr "`{tz}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1497 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1503 #, no-wrap msgid "`{rigoletto}`" msgstr "`{rigoletto}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1500 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1506 #, no-wrap msgid "`{kaktus}`" msgstr "`{kaktus}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1503 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1509 #, no-wrap msgid "`{samm}`" msgstr "`{samm}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1506 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1512 #, no-wrap msgid "`{arrowd}`" msgstr "`{arrowd}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1509 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1515 #, no-wrap msgid "`{ronald}`" msgstr "`{ronald}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1512 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1518 #, no-wrap msgid "`{meta}`" msgstr "`{meta}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1515 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1521 #, no-wrap msgid "`{rnagy}`" msgstr "`{rnagy}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1518 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1524 #, no-wrap msgid "`{vvd}`" msgstr "`{vvd}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1521 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1527 #, no-wrap msgid "`{gbe}`" msgstr "`{gbe}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1524 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1530 #, no-wrap msgid "`{bnovkov}`" msgstr "`{bnovkov}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1527 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1533 #, no-wrap msgid "`{ivy}`" msgstr "`{ivy}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1530 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1536 #, no-wrap msgid "`{khorben}`" msgstr "`{khorben}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1533 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1539 #, no-wrap msgid "`{vexeduxr}`" msgstr "`{vexeduxr}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1536 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1542 #, no-wrap msgid "`{alven}`" msgstr "`{alven}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1539 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1545 #, no-wrap msgid "`{pouria}`" msgstr "`{pouria}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1542 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1548 #, no-wrap msgid "`{siva}`" msgstr "`{siva}`" +#. type: Title === +#: documentation/content/en/articles/pgpkeys/_index.adoc:1551 +#, no-wrap +msgid "`{nxjoseph}`" +msgstr "`{nxjoseph}`" + +#. type: Title === +#: documentation/content/en/articles/pgpkeys/_index.adoc:1554 +#, no-wrap +msgid "`{kenrap}`" +msgstr "`{kenrap}`" + #. type: Title == -#: documentation/content/en/articles/pgpkeys/_index.adoc:1546 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1558 #, no-wrap msgid "Other Cluster Account Holders" msgstr "Другие владельцы учётных записей" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1548 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1560 #, no-wrap msgid "`{bk}`" msgstr "`{bk}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1551 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1563 #, no-wrap msgid "`{deb}`" msgstr "`{deb}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1554 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1566 #, no-wrap msgid "`{debdrup}`" msgstr "`{debdrup}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1557 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1569 #, no-wrap msgid "`{dutchdaemon}`" msgstr "`{dutchdaemon}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1560 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1572 #, no-wrap msgid "`{keymaster}`" msgstr "`{keymaster}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1563 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1575 #, no-wrap msgid "`{mwlucas}`" msgstr "`{mwlucas}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1566 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1578 #, no-wrap msgid "`{dhw}`" msgstr "`{dhw}`" #. type: Title === -#: documentation/content/en/articles/pgpkeys/_index.adoc:1569 +#: documentation/content/en/articles/pgpkeys/_index.adoc:1581 #, no-wrap msgid "`{tpearson}`" msgstr "`{tpearson}`" diff --git a/documentation/content/ru/articles/pr-guidelines/_index.adoc b/documentation/content/ru/articles/pr-guidelines/_index.adoc index 4f04742c6f..d8697eb146 100644 --- a/documentation/content/ru/articles/pr-guidelines/_index.adoc +++ b/documentation/content/ru/articles/pr-guidelines/_index.adoc @@ -1,503 +1,503 @@ --- authors: - author: 'Dag-Erling Smørgrav' - author: 'Hiten Pandya' - author: 'Mark Linimon' description: 'Эти рекомендации описывают рекомендуемые методы обработки отчётов о проблемах FreeBSD (PR — Problem Reports).' tags: ["PR", "guideline", "bugs", "maintenance", "BugZilla", "FreeBSD"] title: 'Руководство по обработке отчётов о проблемах с помощью Bugzilla' trademarks: ["freebsd", "general"] --- = Руководство по обработке отчётов о проблемах с помощью Bugzilla :doctype: article :toc: macro :toclevels: 1 :icons: font :sectnums: :sectnumlevels: 6 :source-highlighter: rouge :experimental: :images-path: articles/pr-guidelines/ ifdef::env-beastie[] ifdef::backend-html5[] include::shared/authors.adoc[] include::shared/mirrors.adoc[] include::shared/releases.adoc[] include::shared/attributes/attributes-{{% lang %}}.adoc[] include::shared/{{% lang %}}/teams.adoc[] include::shared/{{% lang %}}/mailing-lists.adoc[] include::shared/{{% lang %}}/urls.adoc[] :imagesdir: ../../../images/{images-path} endif::[] ifdef::backend-pdf,backend-epub3[] include::../../../../shared/asciidoctor.adoc[] endif::[] endif::[] ifndef::env-beastie[] include::../../../../../shared/asciidoctor.adoc[] endif::[] [.abstract-title] Аннотация Эти рекомендации описывают рекомендуемые методы работы с отчётами о проблемах FreeBSD (PR), отправленных в Bugzilla. Хотя они разработаны для команды сопровождения базы данных FreeBSD Bugzilla mailto:freebsd-bugbusters@FreeBSD.org[freebsd-bugbusters@FreeBSD.org], эти рекомендации следует соблюдать всем, кто работает с отчётами о проблемах FreeBSD. ''' toc::[] [[intro]] == Введение Bugzilla — это система управления задачами, используемая проектом FreeBSD. Поскольку точный учёт неисправленных программных ошибок важен для качества FreeBSD, правильное использование данного ПО критически необходимо для развития проекта. Доступ к Bugzilla предоставлен всему сообществу FreeBSD. Для поддержания согласованности в базе данных и обеспечения единообразного взаимодействия с пользователями были установлены руководящие принципы, охватывающие общие аспекты управления ошибками, такие как предоставление последующих действий, обработка запросов на закрытие и так далее. Примечание: в этой статье под термином «PR» понимается «отчёт о проблеме в Bugzilla» (Bugzilla Problem Report). [[pr-lifecycle]] == Жизненный цикл отчёта о проблеме [NOTE] ==== Данный раздел устарел и переписывается по состоянию на январь 2026 года. ==== * Репортер отправляет отчёт об ошибке на веб-сайте. Ошибка находится в состоянии `Needs Triage`. * Джейн Рэндом БагБастер подтверждает, что отчёт об ошибке содержит достаточно информации для её воспроизведения. Если нет, она взаимодействует с отправителем, чтобы получить необходимые данные. На этом этапе ошибке присваивается статус `Open`. * Джо Рандом Коммиттер проявляет интерес к отчёту и назначает его себе, или Джейн Рандом БагБастер решает, что Джо лучше всего подходит для его решения и назначает его Джону. Ошибка должна быть переведена в состояние `In Discussion`. * Джо кратко общается с инициатором (убедившись, что всё заносится в журнал аудита) и определяет причину проблемы. -* Джо засиживается всю ночь и создает патч, который, как он считает, исправляет проблему, и отправляет его в ответном сообщении, прося автора проверить его. Затем он устанавливает состояние отчёта в `Patch Ready`. +* Джо засиживается всю ночь и создаёт патч, который, как он считает, исправляет проблему, и отправляет его в ответном сообщении, прося автора проверить его. Затем он устанавливает состояние отчёта в `Patch Ready`. * После нескольких итераций и Джо, и автор патча остаются довольны результатом, и Джо фиксирует его в `-CURRENT` (или напрямую в `-STABLE`, если проблема отсутствует в `-CURRENT`), обязательно указывая в логе коммита ссылку на отчёт о проблеме (а также упоминая автора, если он предоставил патч целиком или частично) и, если необходимо, запускает отсчёт для MFC. Ошибка переводится в состояние `Needs MFC`. * Если исправление не требует переноса в стабильную ветку (MFC), Джо закрывает отчёт с пометкой `Issue Resolved`. [NOTE] ==== Многие отчётов отправляются с очень небольшим количеством информации о проблеме, а некоторые либо очень сложны для решения, либо лишь поверхностно затрагивают более крупную проблему; в таких случаях крайне важно получить всю необходимую информацию для решения проблемы. Если проблему внутри нельзя решить или она возникла снова, необходимо переоткрыть отчёт. ==== [[pr-states]] == Состояние отчёта о проблеме [NOTE] ==== Данный раздел устарел и переписывается по состоянию на январь 2026 года. ==== Важно обновлять состояние отчёта о проблеме при выполнении определённых действий. Состояние должно точно отражать текущий статус работы над проблемой. .Небольшой пример, когда следует изменить состояние PR [example] ==== Когда работа над PR завершена и ответственные разработчики уверены в исправлении, они отправят обновление в PR и изменят его состояние на «feedback». На этом этапе автор должен оценить исправление в своём контексте и ответить, была ли действительно устранена проблема. ==== Отчёт о проблеме может находиться в одном из следующих состояний: open (открыто):: Начальное состояние; проблема была указана и требует рассмотрения. analyzed (проанализировано):: Проблема была рассмотрена, и решение находится в разработке. feedback (обратная связь):: Дальнейшая работа требует дополнительной информации от инициатора или сообщества; возможно, информации относительно предлагаемого решения. patched (исправлено):: Патч был закоммичен, но что-то (MFC или, возможно, подтверждение от автора) ещё ожидается. suspended (приостановлено):: Проблема не решается из-за недостатка информации или ресурсов. Это отличный вариант для тех, кто ищет проект для реализации. Если проблему не удастся решить вовсе, она будет закрыта, а не приостановлена. Документационный проект использует статус «приостановлено» для пунктов списка пожеланий, требующих значительного объёма работы, на который у участников сейчас нет времени. closed (закрыто):: Проблемный отчёт закрывается, когда все изменения внедрены, задокументированы и протестированы, или когда исправление проблемы прекращено. [NOTE] ==== Состояние "исправлено" (patched) напрямую связано с обратной связью, поэтому вы можете перейти сразу в состояние "закрыто", если автор не может протестировать исправление, и оно работает в ваших собственных тестах. ==== [[pr-types]] == Типы отчётов о проблемах При обработке отчётов о проблемах, будь вы разработчиком с прямым доступом к базе данных отчётов или участником, который просматривает базу данных и отправляет ответы с исправлениями, комментариями, предложениями или запросами на изменения, вы столкнетесь с несколькими различными типами PR. * crossref:pr-guidelines[pr-unassigned, Неназначенные PR] * crossref:pr-guidelines[pr-assigned, Назначенные PR] * crossref:pr-guidelines[pr-dups, Дублирующие PR] * crossref:pr-guidelines[pr-stale, Устаревшие PR] * crossref:pr-guidelines[pr-misfiled-notpr, Несвязанные с ошибками PR] Следующие разделы описывают, для чего используется каждый из различных типов PR, когда PR относится к одному из этих типов и как обрабатывается каждый из различных типов. [[pr-unassigned]] == Неназначенные PR Когда поступают PR, они изначально назначаются на обобщённого исполнителя. Такие исполнители всегда начинаются с префикса `freebsd-`. Точное значение по умолчанию зависит от категории; в большинстве случаев оно соответствует определённому списку рассылки FreeBSD. Вот текущий список, с наиболее распространёнными значениями в начале: [[default-assignees-common]] .Назначенные по умолчанию исполнители — наиболее распространённые [cols="1,1,1", options="header"] |=== | Тип | Категории | Назначенный по умолчанию |базовая система |bin, conf, gnu, kern, misc |freebsd-bugs |специфичные от архитектуры |arm, amd64, i386, mips |freebsd-_arch_ |специфичные от архитектуры: powerpc |powerpc64 |freebsd-ppc |специфичные от архитектуры: riscv64 |riscv64 |freebsd-risc |коллекция портов |ports |freebsd-ports-bugs |документация, поставляемая с системой |docs |freebsd-doc |веб-страницы FreeBSD (за исключением документации) |Website |freebsd-www |=== [[default-assignees-other]] .Назначенные по умолчанию - другие [cols="1,1,1", options="header"] |=== | Тип | Категории | Назначенный по умолчанию |усилия по продвижению |advocacy |freebsd-advocacy |проблемы с Java Virtual Machine(TM) |java |freebsd-java |соответствие стандартам |standards |freebsd-standards |библиотеки потоков |threads |freebsd-threads |подсистема man:usb[4] |usb |freebsd-usb |=== Не удивляйтесь, если обнаружите, что автор PR назначил ему неверную категорию. Если вы исправите категорию, не забудьте также исправить назначение. (В частности, наши авторы, похоже, с трудом понимают, что даже если их проблема проявилась на системе i386, она может быть общей для всей FreeBSD и, следовательно, более уместна в `kern`. Обратное, конечно, тоже верно.) Некоторые PR могут быть переназначены с этих общих ответственных любым человеком. Существует несколько типов ответственных: специализированные почтовые рассылки, почтовые алиасы (используются для определённых элементов с ограниченным интересом) и отдельные лица. Для назначений, которые являются списками рассылки, используйте полную форму при назначении (например, `freebsd-foo` вместо `foo`); это позволит избежать дублирования писем, отправляемых в список рассылки. [NOTE] ==== Поскольку список людей, которые добровольно согласились быть ответственными по умолчанию за определённые типы PR, меняется так часто, эта информация гораздо лучше подходит для https://wiki.freebsd.org/AssigningPRs[вики FreeBSD]. ==== Вот примерный список таких объектов; возможно, он не полный. [[common-assignees-base]] .Общие ответственные исполнители — базовая система [cols="1,1,1,1", options="header"] |=== | Тип | Предполагаемая категория | Предполагаемый исполнитель | Тип Назначенного |проблема, специфичная для архитектуры ARM(R) |arm |freebsd-arm |список рассылки |проблема, специфичная для архитектуры MIPS(R) |kern |freebsd-mips |список рассылки |проблема, специфичная для архитектуры PowerPC(R) |kern |freebsd-ppc |список рассылки |проблема с Advanced Configuration and Power Management (man:acpi[4]) |kern |freebsd-acpi |список рассылки |проблема со встроенными или компактными системами FreeBSD (например, NanoBSD/PicoBSD/FreeBSD-arm) |kern |freebsd-embedded |список рассылки |проблема с драйверами FireWire(R) |kern |freebsd-firewire |список рассылки |проблема с кодом файловой системы |kern |freebsd-fs |список рассылки |проблема с подсистемой man:geom[4] |kern |freebsd-geom |список рассылки |проблема с подсистемой man:ipfw[4] |kern |freebsd-ipfw |список рассылки |подсистема man:jail[8] |kern |freebsd-jail |список рассылки |проблема с эмуляцией Linux(R) или SVR4 |kern |freebsd-emulation |список рассылки |проблема со стеком сетевых протоколов |kern |freebsd-net |список рассылки |проблема с подсистемой man:pf[4] |kern |freebsd-pf |список рассылки |проблема с подсистемой man:scsi[4] |kern |freebsd-scsi |список рассылки |проблема с подсистемой man:sound[4] |kern |freebsd-multimedia |список рассылки |проблемы с подсистемой man:wlan[4] и беспроводными драйверами |kern |freebsd-wireless |список рассылки |проблема с man:sysinstall[8] или man:bsdinstall[8] |bin |freebsd-sysinstall |список рассылки |проблема со скриптами запуска системы (man:rc[8]) |kern |freebsd-rc |список рассылки |проблема с функциональностью VIMAGE или VNET и связанным кодом |kern |freebsd-virtualization |список рассылки |проблема с эмуляцией Xen |kern |freebsd-xen |список рассылки |=== [[common-assignees-ports]] .Общие ответственные исполнители — Коллекция портов [cols="1,1,1,1", options="header"] |=== | Тип | Предполагаемая категория | Предполагаемый исполнитель | Тип Назначенного |проблема с фреймворком портов (__не__ с отдельным портом!) |ports |portmgr |alias |порт, который поддерживается apache@FreeBSD.org |ports |apache |список рассылки |порт, который поддерживается autotools@FreeBSD.org |ports |autotools |alias |порт, который поддерживается doceng@FreeBSD.org |ports |doceng |alias |порт, который поддерживается eclipse@FreeBSD.org |ports |freebsd-eclipse |список рассылки |порт, который поддерживается gecko@FreeBSD.org |ports |gecko |список рассылки |порт, который поддерживается gnome@FreeBSD.org |ports |gnome |список рассылки |порт, который поддерживается hamradio@FreeBSD.org |ports |hamradio |alias |порт, который поддерживается haskell@FreeBSD.org |ports |haskell |alias |порт, который поддерживается java@FreeBSD.org |ports |freebsd-java |список рассылки |порт, который поддерживается kde@FreeBSD.org |ports |kde |список рассылки |порт, который поддерживается mono@FreeBSD.org |ports |mono |список рассылки |порт, который поддерживается office@FreeBSD.org |ports |freebsd-office |список рассылки |порт, который поддерживается perl@FreeBSD.org |ports |perl |список рассылки |порт, который поддерживается python@FreeBSD.org |ports |freebsd-python |список рассылки |порт, который поддерживается ruby@FreeBSD.org |ports |freebsd-ruby |список рассылки |порт, который поддерживается secteam@FreeBSD.org |ports |secteam |alias |порт, который поддерживается vbox@FreeBSD.org |ports |vbox |alias |порт, который поддерживается x11@FreeBSD.org |ports |freebsd-x11 |список рассылки |=== PR портов, у которых есть сопровождающий, являющийся коммиттером портов, могут быть переназначены кем угодно (но обратите внимание, что не каждый коммиттер FreeBSD обязательно является коммиттером портов, поэтому нельзя ориентироваться только на адрес электронной почты.) Для других PR (запросов на включение изменений) не перераспределяйте их между участниками (кроме себя), если вы не уверены, что назначенный участник действительно хочет отслеживать PR. Это поможет избежать ситуации, когда никто не занимается исправлением конкретной проблемы, потому что все предполагают, что назначенный участник уже работает над ней. [[common-assignees-other]] .Общие ответственные исполнители — Прочие [cols="1,1,1,1", options="header"] |=== | Тип | Предполагаемая категория | Предполагаемый исполнитель | Тип Назначенного |проблема с базой данных отчётов о проблемах |bin |bugmeister |alias |проблема с https://bugs.freebsd.org/submit/[веб-формой] Bugzilla. |doc |bugmeister |alias |=== [[pr-assigned]] == Назначенные PR Если в PR поле `responsible` содержит имя пользователя разработчика FreeBSD, это означает, что PR передан этому конкретному человеку для дальнейшей работы. Назначенные PR не должны изменяться никем, кроме назначенного исполнителя или bugmeister. Если у вас есть комментарии, отправьте последующее сообщение. Если по какой-либо причине вы считаете, что PR должен изменить состояние или быть переназначен, отправьте сообщение назначенному исполнителю. Если назначенный исполнитель не ответит в течение двух недель, снимите назначение с PR и действуйте по своему усмотрению. [[pr-dups]] == Дублирующие PR Если вы обнаружили несколько PR, описывающих одну и ту же проблему, выберите тот, который содержит наибольшее количество полезной информации, и закройте остальные, явно указав номер заменяющего PR. Если в нескольких PR содержится неперекрывающаяся полезная информация, добавьте всю недостающую информацию в один из них в виде последующего сообщения, включая ссылки на остальные PR; затем закройте другие PR (которые теперь полностью заменены). [[pr-stale]] == Устаревшие PR PR считается устаревшим, если он не изменялся более шести месяцев. Для обработки устаревших PR примените следующую процедуру: * Если PR содержит достаточно деталей, попробуйте воспроизвести проблему в `-CURRENT` и `-STABLE`. Если удастся, отправьте уточнение с вашими находками и попытайтесь найти, кому можно назначить задачу. Установите состояние "analyzed" (проанализировано), если это уместно. * Если PR описывает проблему, которая, как вам известно, является результатом ошибки использования (неправильной конфигурации или иной), отправьте комментарий с объяснением, что сделал не так автор, затем закройте PR с причиной "Ошибка пользователя" или "Ошибка конфигурации". * Если PR описывает ошибку, которая, как вам известно, была исправлена в обеих ветках `-CURRENT` и `-STABLE`, закройте его с сообщением, указывающим, когда она была исправлена в каждой из веток. * Если PR описывает ошибку, которая, как вам известно, исправлена в `-CURRENT`, но не в `-STABLE`, попытайтесь выяснить, когда планируется перенос исправления (MFC), или найдите кого-то (возможно, себя?), кто сможет это сделать. Установите статус "patched" и назначьте задачу тому, кто займётся переносом исправления (MFC). * В других случаях попросите автора подтвердить, сохраняется ли проблема в более новых версиях. Если автор не ответит в течение месяца, закройте PR с пометкой "Истекло время ожидания ответа". [[pr-misfiled-notpr]] == Не связанные с ошибками PR Разработчики, которые сталкиваются с PR, которые, по их мнению, должны были быть отправлены в {freebsd-bugs} или какой-либо другой список, должны закрыть PR, сообщив отправителю в комментарии, почему это не является PR и куда следует отправить сообщение. Адреса электронной почты, которые Bugzilla использует для входящих PR, были опубликованы как часть документации FreeBSD, объявлены и перечислены на веб-сайте. Это означает, что спамеры их обнаружили. Всякий раз, когда вы закрываете один из этих PR, пожалуйста, выполните следующее: * Установите компонент в значение `junk` (в разделе `Поддерживающие сервисы`). * Установить Responsible в `nobody@FreeBSD.org`. * Установите состояние `Issue Resolved`. Установка категории в `junk` делает очевидным отсутствие полезного содержимого в PR и помогает уменьшить беспорядок в основных категориях. [[references]] == Для дальнейшего ознакомления Это список информационных ресурсов, относящихся к правильному написанию и обработке сообщений о проблемах. Он, без сомнения, не полон. * extref:{problem-reports}[Как писать отчёты о проблемах в FreeBSD]-рекомендации для авторов отчётов. diff --git a/documentation/content/ru/articles/pr-guidelines/_index.po b/documentation/content/ru/articles/pr-guidelines/_index.po index 759e6822a2..f221cefb00 100644 --- a/documentation/content/ru/articles/pr-guidelines/_index.po +++ b/documentation/content/ru/articles/pr-guidelines/_index.po @@ -1,1636 +1,1636 @@ # SOME DESCRIPTIVE TITLE # Copyright (C) YEAR The FreeBSD Project # This file is distributed under the same license as the FreeBSD Documentation package. # Vladlen Popolitov , 2025, 2026. msgid "" msgstr "" "Project-Id-Version: FreeBSD Documentation VERSION\n" "POT-Creation-Date: 2026-02-22 15:58+0000\n" -"PO-Revision-Date: 2026-03-08 09:11+0000\n" +"PO-Revision-Date: 2026-04-05 04:45+0000\n" "Last-Translator: Vladlen Popolitov \n" "Language-Team: Russian \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "X-Generator: Weblate 4.17\n" #. type: YAML Front Matter: description #: documentation/content/en/articles/pr-guidelines/_index.adoc:1 #, no-wrap msgid "These guidelines describe recommended handling practices for FreeBSD Problem Reports (PRs)." msgstr "Эти рекомендации описывают рекомендуемые методы обработки отчётов о проблемах FreeBSD (PR — Problem Reports)." #. type: Title = #: documentation/content/en/articles/pr-guidelines/_index.adoc:1 #: documentation/content/en/articles/pr-guidelines/_index.adoc:12 #, no-wrap msgid "Problem Report Handling Guidelines With Bugzilla" msgstr "Руководство по обработке отчётов о проблемах с помощью Bugzilla" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:45 msgid "Abstract" msgstr "Аннотация" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:48 msgid "" "These guidelines describe recommended handling practices for FreeBSD Problem " "Reports (PRs) as submitted via Bugzilla. Whilst developed for the FreeBSD " "Bugzilla Database Maintenance Team mailto:freebsd-bugbusters@FreeBSD." "org[freebsd-bugbusters@FreeBSD.org], these guidelines should be followed by " "anyone working with FreeBSD Problem Reports." msgstr "" "Эти рекомендации описывают рекомендуемые методы работы с отчётами о " "проблемах FreeBSD (PR), отправленных в Bugzilla. Хотя они разработаны для " "команды сопровождения базы данных FreeBSD Bugzilla mailto:freebsd-" "bugbusters@FreeBSD.org[freebsd-bugbusters@FreeBSD.org], эти рекомендации " "следует соблюдать всем, кто работает с отчётами о проблемах FreeBSD." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:50 msgid "'''" msgstr "'''" #. type: Title == #: documentation/content/en/articles/pr-guidelines/_index.adoc:54 #, no-wrap msgid "Introduction" msgstr "Введение" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:58 msgid "" "Bugzilla is an issue management system used by the FreeBSD Project. As " "accurate tracking of outstanding software defects is important to FreeBSD's " "quality, the correct use of the software is essential to the forward " "progress of the Project." msgstr "" "Bugzilla — это система управления задачами, используемая проектом FreeBSD. " "Поскольку точный учёт неисправленных программных ошибок важен для качества " "FreeBSD, правильное использование данного ПО критически необходимо для " "развития проекта." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:61 msgid "" "Access to Bugzilla is available to the entire FreeBSD community. In order " "to maintain consistency within the database and provide a consistent user " "experience, guidelines have been established covering common aspects of bug " "management such as presenting followup, handling close requests, and so " "forth." msgstr "" "Доступ к Bugzilla предоставлен всему сообществу FreeBSD. Для поддержания " "согласованности в базе данных и обеспечения единообразного взаимодействия с " "пользователями были установлены руководящие принципы, охватывающие общие " "аспекты управления ошибками, такие как предоставление последующих действий, " "обработка запросов на закрытие и так далее." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:63 msgid "" "Note: in this Article, the term \"PR\" means \"Bugzilla Problem Report\"." msgstr "" "Примечание: в этой статье под термином «PR» понимается «отчёт о проблеме в " "Bugzilla» (Bugzilla Problem Report)." #. type: Title == #: documentation/content/en/articles/pr-guidelines/_index.adoc:65 #, no-wrap msgid "Problem Report Life-cycle" msgstr "Жизненный цикл отчёта о проблеме" #. type: delimited block = 4 #: documentation/content/en/articles/pr-guidelines/_index.adoc:70 #: documentation/content/en/articles/pr-guidelines/_index.adoc:91 msgid "This section is obsolete and being rewritten as of January 2026." msgstr "" "Данный раздел устарел и переписывается по состоянию на январь 2026 года." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:72 msgid "" "The Reporter submits a bug report on the website. The bug is in the `Needs " "Triage` state." msgstr "" "Репортер отправляет отчёт об ошибке на веб-сайте. Ошибка находится в " "состоянии `Needs Triage`." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:73 msgid "" "Jane Random BugBuster confirms that the bug report has sufficient " "information to be reproducible. If not, she goes back and forth with the " "reporter to obtain the needed information. At this point the bug is set to " "the `Open` state." msgstr "" "Джейн Рэндом БагБастер подтверждает, что отчёт об ошибке содержит достаточно " "информации для её воспроизведения. Если нет, она взаимодействует с " "отправителем, чтобы получить необходимые данные. На этом этапе ошибке " "присваивается статус `Open`." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:74 msgid "" "Joe Random Committer takes interest in the report and assigns it to himself, " "or Jane Random BugBuster decides that Joe is best suited to handle it and " "assigns it to him. The bug should be set to the `In Discussion` state." msgstr "" "Джо Рандом Коммиттер проявляет интерес к отчёту и назначает его себе, или " "Джейн Рандом БагБастер решает, что Джо лучше всего подходит для его решения " "и назначает его Джону. Ошибка должна быть переведена в состояние `In " "Discussion`." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:75 msgid "" "Joe has a brief exchange with the originator (making sure it all goes into " "the audit trail) and determines the cause of the problem." msgstr "" "Джо кратко общается с инициатором (убедившись, что всё заносится в журнал " "аудита) и определяет причину проблемы." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:76 msgid "" "Joe pulls an all-nighter and whips up a patch that he thinks fixes the " "problem, and submits it in a follow-up, asking the originator to test it. He " "then sets the report's state to `Patch Ready`." msgstr "" -"Джо засиживается всю ночь и создает патч, который, как он считает, " +"Джо засиживается всю ночь и создаёт патч, который, как он считает, " "исправляет проблему, и отправляет его в ответном сообщении, прося автора " "проверить его. Затем он устанавливает состояние отчёта в `Patch Ready`." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:77 msgid "" "A couple of iterations later, both Joe and the originator are satisfied with " "the patch, and Joe commits it to `-CURRENT` (or directly to `-STABLE` if the " "problem does not exist in `-CURRENT`), making sure to reference the Problem " "Report in his commit log (and credit the originator if they submitted all or " "part of the patch) and, if appropriate, start an MFC countdown. The bug is " "set to the `Needs MFC` state." msgstr "" "После нескольких итераций и Джо, и автор патча остаются довольны " "результатом, и Джо фиксирует его в `-CURRENT` (или напрямую в `-STABLE`, " "если проблема отсутствует в `-CURRENT`), обязательно указывая в логе коммита " "ссылку на отчёт о проблеме (а также упоминая автора, если он предоставил " "патч целиком или частично) и, если необходимо, запускает отсчёт для MFC. " "Ошибка переводится в состояние `Needs MFC`." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:78 msgid "" "If the patch does not need MFCing, Joe then closes the report as `Issue " "Resolved`." msgstr "" "Если исправление не требует переноса в стабильную ветку (MFC), Джо закрывает " "отчёт с пометкой `Issue Resolved`." #. type: delimited block = 4 #: documentation/content/en/articles/pr-guidelines/_index.adoc:83 msgid "" "Many reports are submitted with very little information about the problem, " "and some are either very complex to solve, or just scratch the surface of a " "larger problem; in these cases, it is very important to obtain all the " "necessary information needed to solve the problem. If the problem contained " "within cannot be solved, or has occurred again, it is necessary to re-open " "the report." msgstr "" "Многие отчётов отправляются с очень небольшим количеством информации о " "проблеме, а некоторые либо очень сложны для решения, либо лишь поверхностно " "затрагивают более крупную проблему; в таких случаях крайне важно получить " "всю необходимую информацию для решения проблемы. Если проблему внутри нельзя " "решить или она возникла снова, необходимо переоткрыть отчёт." #. type: Title == #: documentation/content/en/articles/pr-guidelines/_index.adoc:86 #, no-wrap msgid "Problem Report State" msgstr "Состояние отчёта о проблеме" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:94 msgid "" "It is important to update the state of a Problem Report when certain actions " "are taken. The state should accurately reflect the current state of work on " "the issue." msgstr "" "Важно обновлять состояние отчёта о проблеме при выполнении определённых " "действий. Состояние должно точно отражать текущий статус работы над " "проблемой." #. type: Block title #: documentation/content/en/articles/pr-guidelines/_index.adoc:95 #, no-wrap msgid "A small example on when to change PR state" msgstr "Небольшой пример, когда следует изменить состояние PR" #. type: delimited block = 4 #: documentation/content/en/articles/pr-guidelines/_index.adoc:100 msgid "" "When a PR has been worked on and the developer(s) responsible feel " "comfortable about the fix, they will submit a followup to the PR and change " "its state to \"feedback\". At this point, the originator should evaluate " "the fix in their context and respond indicating whether the defect has " "indeed been remedied." msgstr "" "Когда работа над PR завершена и ответственные разработчики уверены в " "исправлении, они отправят обновление в PR и изменят его состояние на " "«feedback». На этом этапе автор должен оценить исправление в своём контексте " "и ответить, была ли действительно устранена проблема." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:103 msgid "A Problem Report may be in one of the following states:" msgstr "Отчёт о проблеме может находиться в одном из следующих состояний:" #. type: Labeled list #: documentation/content/en/articles/pr-guidelines/_index.adoc:104 #, no-wrap msgid "open" msgstr "open (открыто)" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:106 msgid "Initial state; the problem has been pointed out and it needs reviewing." msgstr "Начальное состояние; проблема была указана и требует рассмотрения." #. type: Labeled list #: documentation/content/en/articles/pr-guidelines/_index.adoc:107 #, no-wrap msgid "analyzed" msgstr "analyzed (проанализировано)" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:109 msgid "The problem has been reviewed and a solution is being sought." msgstr "Проблема была рассмотрена, и решение находится в разработке." #. type: Labeled list #: documentation/content/en/articles/pr-guidelines/_index.adoc:110 #, no-wrap msgid "feedback" msgstr "feedback (обратная связь)" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:112 msgid "" "Further work requires additional information from the originator or the " "community; possibly information regarding the proposed solution." msgstr "" "Дальнейшая работа требует дополнительной информации от инициатора или " "сообщества; возможно, информации относительно предлагаемого решения." #. type: Labeled list #: documentation/content/en/articles/pr-guidelines/_index.adoc:113 #, no-wrap msgid "patched" msgstr "patched (исправлено)" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:115 msgid "" "A patch has been committed, but something (MFC, or maybe confirmation from " "originator) is still pending." msgstr "" "Патч был закоммичен, но что-то (MFC или, возможно, подтверждение от автора) " "ещё ожидается." #. type: Labeled list #: documentation/content/en/articles/pr-guidelines/_index.adoc:116 #, no-wrap msgid "suspended" msgstr "suspended (приостановлено)" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:121 msgid "" "The problem is not being worked on, due to lack of information or " "resources. This is a prime candidate for somebody who is looking for a " "project to take on. If the problem cannot be solved at all, it will be " "closed, rather than suspended. The documentation project uses suspended for " "wish-list items that entail a significant amount of work which no one " "currently has time for." msgstr "" "Проблема не решается из-за недостатка информации или ресурсов. Это отличный " "вариант для тех, кто ищет проект для реализации. Если проблему не удастся " "решить вовсе, она будет закрыта, а не приостановлена. Документационный " "проект использует статус «приостановлено» для пунктов списка пожеланий, " "требующих значительного объёма работы, на который у участников сейчас нет " "времени." #. type: Labeled list #: documentation/content/en/articles/pr-guidelines/_index.adoc:122 #, no-wrap msgid "closed" msgstr "closed (закрыто)" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:124 msgid "" "A problem report is closed when any changes have been integrated, " "documented, and tested, or when fixing the problem is abandoned." msgstr "" "Проблемный отчёт закрывается, когда все изменения внедрены, " "задокументированы и протестированы, или когда исправление проблемы " "прекращено." #. type: delimited block = 4 #: documentation/content/en/articles/pr-guidelines/_index.adoc:128 msgid "" "The \"patched\" state is directly related to feedback, so you may go " "directly to \"closed\" state if the originator cannot test the patch, and it " "works in your own testing." msgstr "" "Состояние \"исправлено\" (patched) напрямую связано с обратной связью, " "поэтому вы можете перейти сразу в состояние \"закрыто\", если автор не может " "протестировать исправление, и оно работает в ваших собственных тестах." #. type: Title == #: documentation/content/en/articles/pr-guidelines/_index.adoc:131 #, no-wrap msgid "Types of Problem Reports" msgstr "Типы отчётов о проблемах" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:134 msgid "" "While handling problem reports, either as a developer who has direct access " "to the Problem Reports database or as a contributor who browses the database " "and submits followups with patches, comments, suggestions or change " "requests, you will come across several different types of PRs." msgstr "" "При обработке отчётов о проблемах, будь вы разработчиком с прямым доступом к " "базе данных отчётов или участником, который просматривает базу данных и " "отправляет ответы с исправлениями, комментариями, предложениями или " "запросами на изменения, вы столкнетесь с несколькими различными типами PR." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:136 msgid "crossref:pr-guidelines[pr-unassigned, Unassigned PRs]" msgstr "crossref:pr-guidelines[pr-unassigned, Неназначенные PR]" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:137 msgid "crossref:pr-guidelines[pr-assigned, Assigned PRs]" msgstr "crossref:pr-guidelines[pr-assigned, Назначенные PR]" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:138 msgid "crossref:pr-guidelines[pr-dups, Duplicate PRs]" msgstr "crossref:pr-guidelines[pr-dups, Дублирующие PR]" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:139 msgid "crossref:pr-guidelines[pr-stale, Stale PRs]" msgstr "crossref:pr-guidelines[pr-stale, Устаревшие PR]" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:140 msgid "crossref:pr-guidelines[pr-misfiled-notpr, Non-Bug PRs]" msgstr "crossref:pr-guidelines[pr-misfiled-notpr, Несвязанные с ошибками PR]" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:142 msgid "" "The following sections describe what each different type of PRs is used for, " "when a PR belongs to one of these types, and what treatment each different " "type receives." msgstr "" "Следующие разделы описывают, для чего используется каждый из различных типов " "PR, когда PR относится к одному из этих типов и как обрабатывается каждый из " "различных типов." #. type: Title == #: documentation/content/en/articles/pr-guidelines/_index.adoc:144 #, no-wrap msgid "Unassigned PRs" msgstr "Неназначенные PR" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:150 msgid "" "When PRs arrive, they are initially assigned to a generic (placeholder) " "assignee. These are always prepended with `freebsd-`. The exact value for " "this default depends on the category; in most cases, it corresponds to a " "specific FreeBSD mailing list. Here is the current list, with the most " "common ones listed first:" msgstr "" "Когда поступают PR, они изначально назначаются на обобщённого исполнителя. " "Такие исполнители всегда начинаются с префикса `freebsd-`. Точное значение " "по умолчанию зависит от категории; в большинстве случаев оно соответствует " "определённому списку рассылки FreeBSD. Вот текущий список, с наиболее " "распространёнными значениями в начале:" #. type: Block title #: documentation/content/en/articles/pr-guidelines/_index.adoc:152 #, no-wrap msgid "Default Assignees - most common" msgstr "Назначенные по умолчанию исполнители — наиболее распространённые" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:156 #: documentation/content/en/articles/pr-guidelines/_index.adoc:193 #: documentation/content/en/articles/pr-guidelines/_index.adoc:240 #: documentation/content/en/articles/pr-guidelines/_index.adoc:350 #: documentation/content/en/articles/pr-guidelines/_index.adoc:460 #, no-wrap msgid "Type" msgstr "Тип" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:157 #: documentation/content/en/articles/pr-guidelines/_index.adoc:194 #, no-wrap msgid "Categories" msgstr "Категории" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:159 #: documentation/content/en/articles/pr-guidelines/_index.adoc:196 #, no-wrap msgid "Default Assignee" msgstr "Назначенный по умолчанию" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:160 #, no-wrap msgid "base system" msgstr "базовая система" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:161 #, no-wrap msgid "bin, conf, gnu, kern, misc" msgstr "bin, conf, gnu, kern, misc" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:163 #, no-wrap msgid "freebsd-bugs" msgstr "freebsd-bugs" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:164 #, no-wrap msgid "architecture-specific" msgstr "специфичные от архитектуры" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:165 #, no-wrap msgid "arm, amd64, i386, mips" msgstr "arm, amd64, i386, mips" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:167 #, no-wrap msgid "freebsd-_arch_" msgstr "freebsd-_arch_" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:168 #, no-wrap msgid "architecture-specific: powerpc" msgstr "специфичные от архитектуры: powerpc" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:169 #, no-wrap msgid "powerpc64" msgstr "powerpc64" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:171 #: documentation/content/en/articles/pr-guidelines/_index.adoc:257 #, no-wrap msgid "freebsd-ppc" msgstr "freebsd-ppc" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:172 #, no-wrap msgid "architecture-specific: riscv64" msgstr "специфичные от архитектуры: riscv64" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:173 #, no-wrap msgid "riscv64" msgstr "riscv64" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:175 #, no-wrap msgid "freebsd-risc" msgstr "freebsd-risc" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:176 #, no-wrap msgid "ports collection" msgstr "коллекция портов" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:177 #: documentation/content/en/articles/pr-guidelines/_index.adoc:356 #: documentation/content/en/articles/pr-guidelines/_index.adoc:361 #: documentation/content/en/articles/pr-guidelines/_index.adoc:366 #: documentation/content/en/articles/pr-guidelines/_index.adoc:371 #: documentation/content/en/articles/pr-guidelines/_index.adoc:376 #: documentation/content/en/articles/pr-guidelines/_index.adoc:381 #: documentation/content/en/articles/pr-guidelines/_index.adoc:386 #: documentation/content/en/articles/pr-guidelines/_index.adoc:391 #: documentation/content/en/articles/pr-guidelines/_index.adoc:396 #: documentation/content/en/articles/pr-guidelines/_index.adoc:401 #: documentation/content/en/articles/pr-guidelines/_index.adoc:406 #: documentation/content/en/articles/pr-guidelines/_index.adoc:411 #: documentation/content/en/articles/pr-guidelines/_index.adoc:416 #: documentation/content/en/articles/pr-guidelines/_index.adoc:421 #: documentation/content/en/articles/pr-guidelines/_index.adoc:426 #: documentation/content/en/articles/pr-guidelines/_index.adoc:431 #: documentation/content/en/articles/pr-guidelines/_index.adoc:436 #: documentation/content/en/articles/pr-guidelines/_index.adoc:441 #: documentation/content/en/articles/pr-guidelines/_index.adoc:446 #, no-wrap msgid "ports" msgstr "ports" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:179 #, no-wrap msgid "freebsd-ports-bugs" msgstr "freebsd-ports-bugs" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:180 #, no-wrap msgid "documentation shipped with the system" msgstr "документация, поставляемая с системой" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:181 #, no-wrap msgid "docs" msgstr "docs" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:183 #, no-wrap msgid "freebsd-doc" msgstr "freebsd-doc" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:184 #, no-wrap msgid "FreeBSD web pages (not including docs)" msgstr "веб-страницы FreeBSD (за исключением документации)" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:185 #, no-wrap msgid "Website" msgstr "Website" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:186 #, no-wrap msgid "freebsd-www" msgstr "freebsd-www" #. type: Block title #: documentation/content/en/articles/pr-guidelines/_index.adoc:189 #, no-wrap msgid "Default Assignees - other" msgstr "Назначенные по умолчанию - другие" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:197 #, no-wrap msgid "advocacy efforts" msgstr "усилия по продвижению" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:198 #, no-wrap msgid "advocacy" msgstr "advocacy" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:200 #, no-wrap msgid "freebsd-advocacy" msgstr "freebsd-advocacy" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:201 #, no-wrap msgid "Java Virtual Machine(TM) problems" msgstr "проблемы с Java Virtual Machine(TM)" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:202 #, no-wrap msgid "java" msgstr "java" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:204 #: documentation/content/en/articles/pr-guidelines/_index.adoc:402 #, no-wrap msgid "freebsd-java" msgstr "freebsd-java" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:205 #, no-wrap msgid "standards compliance" msgstr "соответствие стандартам" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:206 #, no-wrap msgid "standards" msgstr "standards" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:208 #, no-wrap msgid "freebsd-standards" msgstr "freebsd-standards" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:209 #, no-wrap msgid "threading libraries" msgstr "библиотеки потоков" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:210 #, no-wrap msgid "threads" msgstr "threads" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:212 #, no-wrap msgid "freebsd-threads" msgstr "freebsd-threads" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:213 #, no-wrap msgid "man:usb[4] subsystem" msgstr "подсистема man:usb[4]" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:214 #, no-wrap msgid "usb" msgstr "usb" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:215 #, no-wrap msgid "freebsd-usb" msgstr "freebsd-usb" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:221 msgid "" "Do not be surprised to find that the submitter of the PR has assigned it to " "the wrong category. If you fix the category, do not forget to fix the " "assignment as well. (In particular, our submitters seem to have a hard time " "understanding that just because their problem manifested on an i386 system, " "that it might be generic to all of FreeBSD, and thus be more appropriate for " "`kern`. The converse is also true, of course.)" msgstr "" "Не удивляйтесь, если обнаружите, что автор PR назначил ему неверную " "категорию. Если вы исправите категорию, не забудьте также исправить " "назначение. (В частности, наши авторы, похоже, с трудом понимают, что даже " "если их проблема проявилась на системе i386, она может быть общей для всей " "FreeBSD и, следовательно, более уместна в `kern`. Обратное, конечно, тоже " "верно.)" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:224 msgid "" "Certain PRs may be reassigned away from these generic assignees by anyone. " "There are several types of assignees: specialized mailing lists; mail " "aliases (used for certain limited-interest items); and individuals." msgstr "" "Некоторые PR могут быть переназначены с этих общих ответственных любым " "человеком. Существует несколько типов ответственных: специализированные " "почтовые рассылки, почтовые алиасы (используются для определённых элементов " "с ограниченным интересом) и отдельные лица." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:227 msgid "" "For assignees which are mailing lists, please use the long form when making " "the assignment (e.g., `freebsd-foo` instead of `foo`); this will avoid " "duplicate emails sent to the mailing list." msgstr "" "Для назначений, которые являются списками рассылки, используйте полную форму " "при назначении (например, `freebsd-foo` вместо `foo`); это позволит избежать " "дублирования писем, отправляемых в список рассылки." #. type: delimited block = 4 #: documentation/content/en/articles/pr-guidelines/_index.adoc:231 msgid "" "Since the list of individuals who have volunteered to be the default " "assignee for certain types of PRs changes so often, it is much more suitable " "for https://wiki.freebsd.org/AssigningPRs[the FreeBSD wiki]." msgstr "" "Поскольку список людей, которые добровольно согласились быть ответственными " "по умолчанию за определённые типы PR, меняется так часто, эта информация " "гораздо лучше подходит для https://wiki.freebsd.org/AssigningPRs[вики " "FreeBSD]." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:234 msgid "Here is a sample list of such entities; it is probably not complete." msgstr "Вот примерный список таких объектов; возможно, он не полный." #. type: Block title #: documentation/content/en/articles/pr-guidelines/_index.adoc:236 #, no-wrap msgid "Common Assignees - base system" msgstr "Общие ответственные исполнители — базовая система" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:241 #: documentation/content/en/articles/pr-guidelines/_index.adoc:351 #: documentation/content/en/articles/pr-guidelines/_index.adoc:461 #, no-wrap msgid "Suggested Category" msgstr "Предполагаемая категория" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:242 #: documentation/content/en/articles/pr-guidelines/_index.adoc:352 #: documentation/content/en/articles/pr-guidelines/_index.adoc:462 #, no-wrap msgid "Suggested Assignee" msgstr "Предполагаемый исполнитель" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:244 #: documentation/content/en/articles/pr-guidelines/_index.adoc:354 #: documentation/content/en/articles/pr-guidelines/_index.adoc:464 #, no-wrap msgid "Assignee Type" msgstr "Тип Назначенного" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:245 #, no-wrap msgid "problem specific to the ARM(R) architecture" msgstr "проблема, специфичная для архитектуры ARM(R)" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:246 #, no-wrap msgid "arm" msgstr "arm" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:247 #, no-wrap msgid "freebsd-arm" msgstr "freebsd-arm" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:249 #: documentation/content/en/articles/pr-guidelines/_index.adoc:254 #: documentation/content/en/articles/pr-guidelines/_index.adoc:259 #: documentation/content/en/articles/pr-guidelines/_index.adoc:264 #: documentation/content/en/articles/pr-guidelines/_index.adoc:269 #: documentation/content/en/articles/pr-guidelines/_index.adoc:274 #: documentation/content/en/articles/pr-guidelines/_index.adoc:279 #: documentation/content/en/articles/pr-guidelines/_index.adoc:284 #: documentation/content/en/articles/pr-guidelines/_index.adoc:289 #: documentation/content/en/articles/pr-guidelines/_index.adoc:294 #: documentation/content/en/articles/pr-guidelines/_index.adoc:299 #: documentation/content/en/articles/pr-guidelines/_index.adoc:304 #: documentation/content/en/articles/pr-guidelines/_index.adoc:309 #: documentation/content/en/articles/pr-guidelines/_index.adoc:314 #: documentation/content/en/articles/pr-guidelines/_index.adoc:319 #: documentation/content/en/articles/pr-guidelines/_index.adoc:324 #: documentation/content/en/articles/pr-guidelines/_index.adoc:329 #: documentation/content/en/articles/pr-guidelines/_index.adoc:334 #: documentation/content/en/articles/pr-guidelines/_index.adoc:339 #: documentation/content/en/articles/pr-guidelines/_index.adoc:343 #: documentation/content/en/articles/pr-guidelines/_index.adoc:364 #: documentation/content/en/articles/pr-guidelines/_index.adoc:379 #: documentation/content/en/articles/pr-guidelines/_index.adoc:384 #: documentation/content/en/articles/pr-guidelines/_index.adoc:389 #: documentation/content/en/articles/pr-guidelines/_index.adoc:404 #: documentation/content/en/articles/pr-guidelines/_index.adoc:409 #: documentation/content/en/articles/pr-guidelines/_index.adoc:414 #: documentation/content/en/articles/pr-guidelines/_index.adoc:419 #: documentation/content/en/articles/pr-guidelines/_index.adoc:424 #: documentation/content/en/articles/pr-guidelines/_index.adoc:429 #: documentation/content/en/articles/pr-guidelines/_index.adoc:434 #: documentation/content/en/articles/pr-guidelines/_index.adoc:448 #, no-wrap msgid "mailing list" msgstr "список рассылки" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:250 #, no-wrap msgid "problem specific to the MIPS(R) architecture" msgstr "проблема, специфичная для архитектуры MIPS(R)" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:251 #: documentation/content/en/articles/pr-guidelines/_index.adoc:256 #: documentation/content/en/articles/pr-guidelines/_index.adoc:261 #: documentation/content/en/articles/pr-guidelines/_index.adoc:266 #: documentation/content/en/articles/pr-guidelines/_index.adoc:271 #: documentation/content/en/articles/pr-guidelines/_index.adoc:276 #: documentation/content/en/articles/pr-guidelines/_index.adoc:281 #: documentation/content/en/articles/pr-guidelines/_index.adoc:286 #: documentation/content/en/articles/pr-guidelines/_index.adoc:291 #: documentation/content/en/articles/pr-guidelines/_index.adoc:296 #: documentation/content/en/articles/pr-guidelines/_index.adoc:301 #: documentation/content/en/articles/pr-guidelines/_index.adoc:306 #: documentation/content/en/articles/pr-guidelines/_index.adoc:311 #: documentation/content/en/articles/pr-guidelines/_index.adoc:316 #: documentation/content/en/articles/pr-guidelines/_index.adoc:321 #: documentation/content/en/articles/pr-guidelines/_index.adoc:331 #: documentation/content/en/articles/pr-guidelines/_index.adoc:336 #: documentation/content/en/articles/pr-guidelines/_index.adoc:341 #, no-wrap msgid "kern" msgstr "kern" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:252 #, no-wrap msgid "freebsd-mips" msgstr "freebsd-mips" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:255 #, no-wrap msgid "problem specific to the PowerPC(R) architecture" msgstr "проблема, специфичная для архитектуры PowerPC(R)" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:260 #, no-wrap msgid "problem with Advanced Configuration and Power Management (man:acpi[4])" msgstr "проблема с Advanced Configuration and Power Management (man:acpi[4])" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:262 #, no-wrap msgid "freebsd-acpi" msgstr "freebsd-acpi" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:265 #, no-wrap msgid "problem with embedded or small-footprint FreeBSD systems (e.g., NanoBSD/PicoBSD/FreeBSD-arm)" msgstr "проблема со встроенными или компактными системами FreeBSD (например, NanoBSD/PicoBSD/FreeBSD-arm)" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:267 #, no-wrap msgid "freebsd-embedded" msgstr "freebsd-embedded" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:270 #, no-wrap msgid "problem with FireWire(R) drivers" msgstr "проблема с драйверами FireWire(R)" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:272 #, no-wrap msgid "freebsd-firewire" msgstr "freebsd-firewire" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:275 #, no-wrap msgid "problem with the filesystem code" msgstr "проблема с кодом файловой системы" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:277 #, no-wrap msgid "freebsd-fs" msgstr "freebsd-fs" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:280 #, no-wrap msgid "problem with the man:geom[4] subsystem" msgstr "проблема с подсистемой man:geom[4]" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:282 #, no-wrap msgid "freebsd-geom" msgstr "freebsd-geom" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:285 #, no-wrap msgid "problem with the man:ipfw[4] subsystem" msgstr "проблема с подсистемой man:ipfw[4]" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:287 #, no-wrap msgid "freebsd-ipfw" msgstr "freebsd-ipfw" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:290 #, no-wrap msgid "man:jail[8] subsystem" msgstr "подсистема man:jail[8]" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:292 #, no-wrap msgid "freebsd-jail" msgstr "freebsd-jail" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:295 #, no-wrap msgid "problem with Linux(R) or SVR4 emulation" msgstr "проблема с эмуляцией Linux(R) или SVR4" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:297 #, no-wrap msgid "freebsd-emulation" msgstr "freebsd-emulation" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:300 #, no-wrap msgid "problem with the networking stack" msgstr "проблема со стеком сетевых протоколов" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:302 #, no-wrap msgid "freebsd-net" msgstr "freebsd-net" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:305 #, no-wrap msgid "problem with the man:pf[4] subsystem" msgstr "проблема с подсистемой man:pf[4]" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:307 #, no-wrap msgid "freebsd-pf" msgstr "freebsd-pf" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:310 #, no-wrap msgid "problem with the man:scsi[4] subsystem" msgstr "проблема с подсистемой man:scsi[4]" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:312 #, no-wrap msgid "freebsd-scsi" msgstr "freebsd-scsi" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:315 #, no-wrap msgid "problem with the man:sound[4] subsystem" msgstr "проблема с подсистемой man:sound[4]" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:317 #, no-wrap msgid "freebsd-multimedia" msgstr "freebsd-multimedia" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:320 #, no-wrap msgid "problems with the man:wlan[4] subsystem and wireless drivers" msgstr "проблемы с подсистемой man:wlan[4] и беспроводными драйверами" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:322 #, no-wrap msgid "freebsd-wireless" msgstr "freebsd-wireless" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:325 #, no-wrap msgid "problem with man:sysinstall[8] or man:bsdinstall[8]" msgstr "проблема с man:sysinstall[8] или man:bsdinstall[8]" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:326 #: documentation/content/en/articles/pr-guidelines/_index.adoc:466 #, no-wrap msgid "bin" msgstr "bin" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:327 #, no-wrap msgid "freebsd-sysinstall" msgstr "freebsd-sysinstall" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:330 #, no-wrap msgid "problem with the system startup scripts (man:rc[8])" msgstr "проблема со скриптами запуска системы (man:rc[8])" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:332 #, no-wrap msgid "freebsd-rc" msgstr "freebsd-rc" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:335 #, no-wrap msgid "problem with VIMAGE or VNET functionality and related code" msgstr "проблема с функциональностью VIMAGE или VNET и связанным кодом" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:337 #, no-wrap msgid "freebsd-virtualization" msgstr "freebsd-virtualization" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:340 #, no-wrap msgid "problem with Xen emulation" msgstr "проблема с эмуляцией Xen" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:342 #, no-wrap msgid "freebsd-xen" msgstr "freebsd-xen" #. type: Block title #: documentation/content/en/articles/pr-guidelines/_index.adoc:346 #, no-wrap msgid "Common Assignees - Ports Collection" msgstr "Общие ответственные исполнители — Коллекция портов" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:355 #, no-wrap msgid "problem with the ports framework (__not__ with an individual port!)" msgstr "проблема с фреймворком портов (__не__ с отдельным портом!)" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:357 #, no-wrap msgid "portmgr" msgstr "portmgr" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:359 #: documentation/content/en/articles/pr-guidelines/_index.adoc:369 #: documentation/content/en/articles/pr-guidelines/_index.adoc:374 #: documentation/content/en/articles/pr-guidelines/_index.adoc:394 #: documentation/content/en/articles/pr-guidelines/_index.adoc:399 #: documentation/content/en/articles/pr-guidelines/_index.adoc:439 #: documentation/content/en/articles/pr-guidelines/_index.adoc:444 #: documentation/content/en/articles/pr-guidelines/_index.adoc:469 #: documentation/content/en/articles/pr-guidelines/_index.adoc:473 #, no-wrap msgid "alias" msgstr "alias" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:360 #, no-wrap msgid "port which is maintained by apache@FreeBSD.org" msgstr "порт, который поддерживается apache@FreeBSD.org" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:362 #, no-wrap msgid "apache" msgstr "apache" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:365 #, no-wrap msgid "port which is maintained by autotools@FreeBSD.org" msgstr "порт, который поддерживается autotools@FreeBSD.org" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:367 #, no-wrap msgid "autotools" msgstr "autotools" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:370 #, no-wrap msgid "port which is maintained by doceng@FreeBSD.org" msgstr "порт, который поддерживается doceng@FreeBSD.org" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:372 #, no-wrap msgid "doceng" msgstr "doceng" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:375 #, no-wrap msgid "port which is maintained by eclipse@FreeBSD.org" msgstr "порт, который поддерживается eclipse@FreeBSD.org" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:377 #, no-wrap msgid "freebsd-eclipse" msgstr "freebsd-eclipse" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:380 #, no-wrap msgid "port which is maintained by gecko@FreeBSD.org" msgstr "порт, который поддерживается gecko@FreeBSD.org" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:382 #, no-wrap msgid "gecko" msgstr "gecko" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:385 #, no-wrap msgid "port which is maintained by gnome@FreeBSD.org" msgstr "порт, который поддерживается gnome@FreeBSD.org" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:387 #, no-wrap msgid "gnome" msgstr "gnome" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:390 #, no-wrap msgid "port which is maintained by hamradio@FreeBSD.org" msgstr "порт, который поддерживается hamradio@FreeBSD.org" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:392 #, no-wrap msgid "hamradio" msgstr "hamradio" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:395 #, no-wrap msgid "port which is maintained by haskell@FreeBSD.org" msgstr "порт, который поддерживается haskell@FreeBSD.org" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:397 #, no-wrap msgid "haskell" msgstr "haskell" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:400 #, no-wrap msgid "port which is maintained by java@FreeBSD.org" msgstr "порт, который поддерживается java@FreeBSD.org" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:405 #, no-wrap msgid "port which is maintained by kde@FreeBSD.org" msgstr "порт, который поддерживается kde@FreeBSD.org" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:407 #, no-wrap msgid "kde" msgstr "kde" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:410 #, no-wrap msgid "port which is maintained by mono@FreeBSD.org" msgstr "порт, который поддерживается mono@FreeBSD.org" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:412 #, no-wrap msgid "mono" msgstr "mono" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:415 #, no-wrap msgid "port which is maintained by office@FreeBSD.org" msgstr "порт, который поддерживается office@FreeBSD.org" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:417 #, no-wrap msgid "freebsd-office" msgstr "freebsd-office" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:420 #, no-wrap msgid "port which is maintained by perl@FreeBSD.org" msgstr "порт, который поддерживается perl@FreeBSD.org" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:422 #, no-wrap msgid "perl" msgstr "perl" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:425 #, no-wrap msgid "port which is maintained by python@FreeBSD.org" msgstr "порт, который поддерживается python@FreeBSD.org" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:427 #, no-wrap msgid "freebsd-python" msgstr "freebsd-python" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:430 #, no-wrap msgid "port which is maintained by ruby@FreeBSD.org" msgstr "порт, который поддерживается ruby@FreeBSD.org" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:432 #, no-wrap msgid "freebsd-ruby" msgstr "freebsd-ruby" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:435 #, no-wrap msgid "port which is maintained by secteam@FreeBSD.org" msgstr "порт, который поддерживается secteam@FreeBSD.org" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:437 #, no-wrap msgid "secteam" msgstr "secteam" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:440 #, no-wrap msgid "port which is maintained by vbox@FreeBSD.org" msgstr "порт, который поддерживается vbox@FreeBSD.org" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:442 #, no-wrap msgid "vbox" msgstr "vbox" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:445 #, no-wrap msgid "port which is maintained by x11@FreeBSD.org" msgstr "порт, который поддерживается x11@FreeBSD.org" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:447 #, no-wrap msgid "freebsd-x11" msgstr "freebsd-x11" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:451 msgid "" "Ports PRs which have a maintainer who is a ports committer may be reassigned " "by anyone (but note that not every FreeBSD committer is necessarily a ports " "committer, so you cannot simply go by the email address alone.)" msgstr "" "PR портов, у которых есть сопровождающий, являющийся коммиттером портов, " "могут быть переназначены кем угодно (но обратите внимание, что не каждый " "коммиттер FreeBSD обязательно является коммиттером портов, поэтому нельзя " "ориентироваться только на адрес электронной почты.)" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:454 msgid "" "For other PRs, please do not reassign them to individuals (other than " "yourself) unless you are certain that the assignee really wants to track the " "PR. This will help to avoid the case where no one looks at fixing a " "particular problem because everyone assumes that the assignee is already " "working on it." msgstr "" "Для других PR (запросов на включение изменений) не перераспределяйте их " "между участниками (кроме себя), если вы не уверены, что назначенный участник " "действительно хочет отслеживать PR. Это поможет избежать ситуации, когда " "никто не занимается исправлением конкретной проблемы, потому что все " "предполагают, что назначенный участник уже работает над ней." #. type: Block title #: documentation/content/en/articles/pr-guidelines/_index.adoc:456 #, no-wrap msgid "Common Assignees - Other" msgstr "Общие ответственные исполнители — Прочие" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:465 #, no-wrap msgid "problem with Problem Report database" msgstr "проблема с базой данных отчётов о проблемах" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:467 #: documentation/content/en/articles/pr-guidelines/_index.adoc:472 #, no-wrap msgid "bugmeister" msgstr "bugmeister" #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:470 #, no-wrap msgid "problem with Bugzilla https://bugs.freebsd.org/submit/[web form]." msgstr "проблема с https://bugs.freebsd.org/submit/[веб-формой] Bugzilla." #. type: Table #: documentation/content/en/articles/pr-guidelines/_index.adoc:471 #, no-wrap msgid "doc" msgstr "doc" #. type: Title == #: documentation/content/en/articles/pr-guidelines/_index.adoc:476 #, no-wrap msgid "Assigned PRs" msgstr "Назначенные PR" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:479 msgid "" "If a PR has the `responsible` field set to the username of a FreeBSD " "developer, it means that the PR has been handed over to that particular " "person for further work." msgstr "" "Если в PR поле `responsible` содержит имя пользователя разработчика FreeBSD, " "это означает, что PR передан этому конкретному человеку для дальнейшей " "работы." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:484 msgid "" "Assigned PRs should not be touched by anyone but the assignee or " "bugmeister. If you have comments, submit a followup. If for some reason " "you think the PR should change state or be reassigned, send a message to the " "assignee. If the assignee does not respond within two weeks, unassign the " "PR and do as you please." msgstr "" "Назначенные PR не должны изменяться никем, кроме назначенного исполнителя " "или bugmeister. Если у вас есть комментарии, отправьте последующее " "сообщение. Если по какой-либо причине вы считаете, что PR должен изменить " "состояние или быть переназначен, отправьте сообщение назначенному " "исполнителю. Если назначенный исполнитель не ответит в течение двух недель, " "снимите назначение с PR и действуйте по своему усмотрению." #. type: Title == #: documentation/content/en/articles/pr-guidelines/_index.adoc:486 #, no-wrap msgid "Duplicate PRs" msgstr "Дублирующие PR" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:490 msgid "" "If you find more than one PR that describe the same issue, choose the one " "that contains the largest amount of useful information and close the others, " "stating clearly the number of the superseding PR. If several PRs contain " "non-overlapping useful information, submit all the missing information to " "one in a followup, including references to the others; then close the other " "PRs (which are now completely superseded)." msgstr "" "Если вы обнаружили несколько PR, описывающих одну и ту же проблему, выберите " "тот, который содержит наибольшее количество полезной информации, и закройте " "остальные, явно указав номер заменяющего PR. Если в нескольких PR содержится " "неперекрывающаяся полезная информация, добавьте всю недостающую информацию в " "один из них в виде последующего сообщения, включая ссылки на остальные PR; " "затем закройте другие PR (которые теперь полностью заменены)." #. type: Title == #: documentation/content/en/articles/pr-guidelines/_index.adoc:492 #, no-wrap msgid "Stale PRs" msgstr "Устаревшие PR" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:495 msgid "" "A PR is considered stale if it has not been modified in more than six " "months. Apply the following procedure to deal with stale PRs:" msgstr "" "PR считается устаревшим, если он не изменялся более шести месяцев. Для " "обработки устаревших PR примените следующую процедуру:" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:497 msgid "" "If the PR contains sufficient detail, try to reproduce the problem in `-" "CURRENT` and `-STABLE`. If you succeed, submit a followup detailing your " "findings and try to find someone to assign it to. Set the state to \"analyzed" "\" if appropriate." msgstr "" "Если PR содержит достаточно деталей, попробуйте воспроизвести проблему в `-" "CURRENT` и `-STABLE`. Если удастся, отправьте уточнение с вашими находками и " "попытайтесь найти, кому можно назначить задачу. Установите состояние " "\"analyzed\" (проанализировано), если это уместно." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:498 msgid "" "If the PR describes an issue which you know is the result of a usage error " "(incorrect configuration or otherwise), submit a followup explaining what " "the originator did wrong, then close the PR with the reason \"User error\" " "or \"Configuration error\"." msgstr "" "Если PR описывает проблему, которая, как вам известно, является результатом " "ошибки использования (неправильной конфигурации или иной), отправьте " "комментарий с объяснением, что сделал не так автор, затем закройте PR с " "причиной \"Ошибка пользователя\" или \"Ошибка конфигурации\"." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:499 msgid "" "If the PR describes an error which you know has been corrected in both `-" "CURRENT` and `-STABLE`, close it with a message stating when it was fixed in " "each branch." msgstr "" "Если PR описывает ошибку, которая, как вам известно, была исправлена в обеих " "ветках `-CURRENT` и `-STABLE`, закройте его с сообщением, указывающим, когда " "она была исправлена в каждой из веток." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:500 msgid "" "If the PR describes an error which you know has been corrected in `-" "CURRENT`, but not in `-STABLE`, try to find out when the person who " "corrected it is planning to MFC it, or try to find someone else (maybe " "yourself?) to do it. Set the state to \"patched\" and assign it to whomever " "will do the MFC." msgstr "" "Если PR описывает ошибку, которая, как вам известно, исправлена в `-" "CURRENT`, но не в `-STABLE`, попытайтесь выяснить, когда планируется перенос " "исправления (MFC), или найдите кого-то (возможно, себя?), кто сможет это " "сделать. Установите статус \"patched\" и назначьте задачу тому, кто займётся " "переносом исправления (MFC)." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:501 msgid "" "In other cases, ask the originator to confirm if the problem still exists in " "newer versions. If the originator does not reply within a month, close the " "PR with the notation \"Feedback timeout\"." msgstr "" "В других случаях попросите автора подтвердить, сохраняется ли проблема в " "более новых версиях. Если автор не ответит в течение месяца, закройте PR с " "пометкой \"Истекло время ожидания ответа\"." #. type: Title == #: documentation/content/en/articles/pr-guidelines/_index.adoc:503 #, no-wrap msgid "Non-Bug PRs" msgstr "Не связанные с ошибками PR" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:506 msgid "" "Developers that come across PRs that look like they should have been posted " "to {freebsd-bugs} or some other list should close the PR, informing the " "submitter in a comment why this is not really a PR and where the message " "should be posted." msgstr "" "Разработчики, которые сталкиваются с PR, которые, по их мнению, должны были " "быть отправлены в {freebsd-bugs} или какой-либо другой список, должны " "закрыть PR, сообщив отправителю в комментарии, почему это не является PR и " "куда следует отправить сообщение." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:509 msgid "" "The email addresses that Bugzilla listens to for incoming PRs have been " "published as part of the FreeBSD documentation, have been announced and " "listed on the web-site. This means that spammers found them." msgstr "" "Адреса электронной почты, которые Bugzilla использует для входящих PR, были " "опубликованы как часть документации FreeBSD, объявлены и перечислены на веб-" "сайте. Это означает, что спамеры их обнаружили." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:511 msgid "Whenever you close one of these PRs, please do the following:" msgstr "" "Всякий раз, когда вы закрываете один из этих PR, пожалуйста, выполните " "следующее:" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:513 msgid "Set the component to `junk` (under `Supporting Services`)." msgstr "" "Установите компонент в значение `junk` (в разделе `Поддерживающие сервисы`)." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:514 msgid "Set Responsible to `nobody@FreeBSD.org`." msgstr "Установить Responsible в `nobody@FreeBSD.org`." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:515 msgid "Set State to `Issue Resolved`." msgstr "Установите состояние `Issue Resolved`." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:517 msgid "" "Setting the category to `junk` makes it obvious that there is no useful " "content within the PR, and helps to reduce the clutter within the main " "categories." msgstr "" "Установка категории в `junk` делает очевидным отсутствие полезного " "содержимого в PR и помогает уменьшить беспорядок в основных категориях." #. type: Title == #: documentation/content/en/articles/pr-guidelines/_index.adoc:519 #, no-wrap msgid "Further Reading" msgstr "Для дальнейшего ознакомления" #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:523 msgid "" "This is a list of resources relevant to the proper writing and processing of " "problem reports. It is by no means complete." msgstr "" "Это список информационных ресурсов, относящихся к правильному написанию и " "обработке сообщений о проблемах. Он, без сомнения, не полон." #. type: Plain text #: documentation/content/en/articles/pr-guidelines/_index.adoc:524 msgid "" "extref:{problem-reports}[How to Write FreeBSD Problem Reports]-guidelines " "for Problem Report originators." msgstr "" "extref:{problem-reports}[Как писать отчёты о проблемах в FreeBSD]-" "рекомендации для авторов отчётов." #, no-wrap #~ msgid "alpha, amd64, arm, i386, ia64, powerpc, sparc64" #~ msgstr "alpha, amd64, arm, i386, ia64, powerpc, sparc64" #, no-wrap #~ msgid "problem with Asynchronous Transfer Mode (ATM) drivers" #~ msgstr "проблема с драйверами Asynchronous Transfer Mode (ATM)" #, no-wrap #~ msgid "freebsd-atm" #~ msgstr "freebsd-atm" #, no-wrap #~ msgid "problem with Integrated Services Digital Network (ISDN) drivers" #~ msgstr "проблема с драйверами Integrated Services Digital Network (ISDN)" #, no-wrap #~ msgid "freebsd-isdn" #~ msgstr "freebsd-isdn"