# SOME DESCRIPTIVE TITLE # Copyright (C) YEAR The FreeBSD Project # This file is distributed under the same license as the FreeBSD Documentation package. # Vladlen Popolitov , 2025. 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 \n" "Language-Team: Russian \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "X-Generator: Weblate 4.17\n" #. type: Yaml Front Matter 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]"