Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-doc
Path: blob/main/documentation/content/ru/articles/linux-emulation/_index.po
18096 views
# SOME DESCRIPTIVE TITLE
# Copyright (C) YEAR The FreeBSD Project
# This file is distributed under the same license as the FreeBSD Documentation package.
# Vladlen Popolitov <[email protected]>, 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-04-05 04:45+0000\n"
"Last-Translator: Vladlen Popolitov <[email protected]>\n"
"Language-Team: Russian <https://translate-dev.freebsd.org/projects/"
"documentation/articleslinux-emulation_index/ru/>\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 реализует строгую "
"модель потоков 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]"