diff options
Diffstat (limited to 'documentation/content/ru/articles/linux-emulation/_index.po')
| -rw-r--r-- | documentation/content/ru/articles/linux-emulation/_index.po | 4415 |
1 files changed, 4415 insertions, 0 deletions
diff --git a/documentation/content/ru/articles/linux-emulation/_index.po b/documentation/content/ru/articles/linux-emulation/_index.po new file mode 100644 index 0000000000..0296103bc0 --- /dev/null +++ b/documentation/content/ru/articles/linux-emulation/_index.po @@ -0,0 +1,4415 @@ +# SOME DESCRIPTIVE TITLE +# Copyright (C) YEAR The FreeBSD Project +# This file is distributed under the same license as the FreeBSD Documentation package. +# Vladlen Popolitov <vladlenpopolitov@list.ru>, 2025. +msgid "" +msgstr "" +"Project-Id-Version: FreeBSD Documentation VERSION\n" +"POT-Creation-Date: 2025-10-13 23:41+0300\n" +"PO-Revision-Date: 2025-10-03 04:45+0000\n" +"Last-Translator: Vladlen Popolitov <vladlenpopolitov@list.ru>\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 Hash Value: 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 Hash Value: 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: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:44 +msgid "Abstract" +msgstr "Аннотация" + +#. type: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:176 +msgid "FreeBSD/i386 emulation on FreeBSD/amd64" +msgstr "Совместимость FreeBSD/i386 на FreeBSD/amd64" + +#. type: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:177 +msgid "FreeBSD/i386 emulation on FreeBSD/ia64" +msgstr "FreeBSD/i386 эмуляция на FreeBSD/ia64" + +#. type: .abstract-title +#: 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: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:179 +msgid "NDIS-emulation of Windows networking drivers interface" +msgstr "NDIS-эмуляция интерфейса сетевых драйверов Windows" + +#. type: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:180 +msgid "NetBSD-emulation of NetBSD operating system" +msgstr "NetBSD-эмуляция операционной системы NetBSD" + +#. type: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:181 +msgid "PECoff-support for PECoff FreeBSD executables" +msgstr "Поддержка PECoff для исполняемых файлов FreeBSD в формате PECoff" + +#. type: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:277 +msgid "More information can be obtained from [3]." +msgstr "Дополнительную информацию можно получить из [3]." + +#. type: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:298 +msgid "parameter -> `%ebx`" +msgstr "параметр -> `%ebx`" + +#. type: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:299 +msgid "parameter -> `%ecx`" +msgstr "параметр -> `%ecx`" + +#. type: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:300 +msgid "parameter -> `%edx`" +msgstr "параметр -> `%edx`" + +#. type: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:301 +msgid "parameter -> `%esi`" +msgstr "параметр -> `%esi`" + +#. type: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:302 +msgid "parameter -> `%edi`" +msgstr "параметр -> `%edi`" + +#. type: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:303 +msgid "parameter -> `%ebp`" +msgstr "параметр -> `%ebp`" + +#. type: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:329 +msgid "Implemented clone flags are:" +msgstr "Реализованные флаги клонирования:" + +#. type: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:331 +msgid "`CLONE_VM` - processes share their memory space" +msgstr "`CLONE_VM` - процессы разделяют общее адресное пространство" + +#. type: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:332 +msgid "`CLONE_FS` - share umask, cwd and namespace" +msgstr "" +"`CLONE_FS` — совместно использовать umask, текущий рабочий каталог и " +"пространство имён" + +#. type: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:333 +msgid "`CLONE_FILES` - share open files" +msgstr "`CLONE_FILES` - совместно использовать открытые файлы" + +#. type: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:334 +msgid "`CLONE_SIGHAND` - share signal handlers and blocked signals" +msgstr "" +"`CLONE_SIGHAND` - разделять обработчики сигналов и заблокированные сигналы" + +#. type: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:335 +msgid "`CLONE_PARENT` - share parent" +msgstr "`CLONE_PARENT` - использовать один процесс к качестве родительского" + +#. type: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:336 +msgid "`CLONE_THREAD` - be thread (further explanation below)" +msgstr "`CLONE_THREAD` — быть потоком (дальнейшие пояснения ниже)" + +#. type: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:337 +msgid "`CLONE_NEWNS` - new namespace" +msgstr "`CLONE_NEWNS` - новое пространство имен" + +#. type: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:338 +msgid "`CLONE_SYSVSEM` - share SysV undo structures" +msgstr "`CLONE_SYSVSEM` - совместное использование структур отмены SysV" + +#. type: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:339 +msgid "`CLONE_SETTLS` - setup TLS at supplied address" +msgstr "`CLONE_SETTLS` - настройка TLS по указанному адресу" + +#. type: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:340 +msgid "`CLONE_PARENT_SETTID` - set TID in the parent" +msgstr "`CLONE_PARENT_SETTID` - установить TID в родителе" + +#. type: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:341 +msgid "`CLONE_CHILD_CLEARTID` - clear TID in the child" +msgstr "`CLONE_CHILD_CLEARTID` - очистить TID в дочернем процессе" + +#. type: .abstract-title +#: documentation/content/en/articles/linux-emulation/_index.adoc:342 +msgid "`CLONE_CHILD_SETTID` - set TID in the child" +msgstr "`CLONE_CHILD_SETTID` - установить TID в дочернем процессе" + +#. type: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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: .abstract-title +#: 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. Nevile-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]" |
