Translation projects API.

See the Weblate's Web API documentation for detailed description of the API.

GET /api/projects/documentation/changes/?format=api&page=11280
HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "count": 581037,
    "next": "https://translate-dev.freebsd.org/api/projects/documentation/changes/?format=api&page=11281",
    "previous": "https://translate-dev.freebsd.org/api/projects/documentation/changes/?format=api&page=11279",
    "results": [
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1795977/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.565439Z",
            "action": 9,
            "target": "Системный вызов продолжает выполнение, устанавливая соответствующие флаги в зависимости от переданных аргументов. Например, `CLONE_VM` преобразуется в RFMEM (общее адресное пространство) и т.д. Единственная тонкость здесь — это `CLONE_FS` и `CLONE_FILES`, поскольку FreeBSD не позволяет устанавливать их отдельно, поэтому мы эмулируем это, не устанавливая RFFDG (копирование таблицы файловых дескрипторов и другой информации о файловой системе), если задан любой из этих флагов. Это не вызывает проблем, так как эти флаги всегда устанавливаются вместе.  \n\nПосле установки флагов процесс создаётся с помощью внутренней процедуры `fork1`, при этом процесс настраивается так, чтобы не помещаться в очередь выполнения (т.е. не становиться исполняемым). После завершения ветвления мы, при необходимости, изменяем родителя для нового процесса, чтобы эмулировать семантику `CLONE_PARENT`.  \n\nСледующий шаг — создание данных эмуляции. Потоки в Linux(R) не отправляют сигналы своим родителям, поэтому мы устанавливаем сигнал завершения в 0, чтобы отключить эту возможность. Затем выполняется настройка `child_set_tid` и `child_clear_tid`, что активирует соответствующую функциональность далее в коде. На этом этапе мы копируем PID по адресу, указанному в `parent_tidptr`.  \n\nУстановка стека процесса выполняется простой перезаписью регистра `%esp` (`%rsp` на amd64) в кадре потока. Далее настраивается TLS для нового процесса. После этого может быть эмулирована семантика man:vfork[2], и, наконец, новый процесс помещается в очередь выполнения, а его PID возвращается родительскому процессу через возвращаемое значение `clone`.",
            "id": 878602,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878602/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1795978/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.580434Z",
            "action": 9,
            "target": "Системный вызов `clone` способен и фактически используется для эмуляции классических системных вызовов man:fork[2] и man:vfork[2]. Более новые версии glibc в случае ядра 2.6 используют `clone` для реализации системных вызовов man:fork[2] и man:vfork[2].",
            "id": 878603,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878603/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1795980/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.595432Z",
            "action": 9,
            "target": "Блокировка реализована на уровне подсистем, поскольку не ожидается высокой конкуренции за эти ресурсы. Существует две блокировки: `emul_lock`, используемая для защиты манипуляций с `linux_emuldata`, и `emul_shared_lock`, используемая для манипуляций с `linux_emuldata_shared`. `emul_lock` представляет собой немешающую блокирующую мьютекс, в то время как `emul_shared_lock` — это мешающая блокирующая `sx_lock`. Благодаря блокировке на уровне подсистем мы можем объединять некоторые блокировки, поэтому поиск em предлагает доступ без блокировки.",
            "id": 878604,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878604/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1795982/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.609810Z",
            "action": 9,
            "target": "Этот раздел посвящён TLS, также известному как локальное хранилище потока.",
            "id": 878605,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878605/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1795983/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.624083Z",
            "action": 9,
            "target": "Введение в многопоточность",
            "id": 878606,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878606/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1795984/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.644081Z",
            "action": 9,
            "target": "В компьютерных науках потоки (threads) — это сущности внутри процесса, которые могут планироваться независимо друг от друга. Потоки в процессе разделяют общие данные процесса (например, файловые дескрипторы), но также имеют свой собственный стек для своих данных. Иногда возникает необходимость в данных, специфичных для конкретного потока, но доступных на уровне процесса. Например, имя выполняемого потока или что-то подобное.  \n\nТрадиционный API для работы с потоками в UNIX® — pthreads — предоставляет способ сделать это через функции `man:pthread_key_create[3]`, `man:pthread_setspecific[3]` и `man:pthread_getspecific[3]`, где поток может создать ключ к локальным данным потока и использовать `man:pthread_getspecific[3]` или `man:pthread_getspecific[3]` для управления этими данными. Легко заметить, что это не самый удобный способ.  \n\nПоэтому различные разработчики компиляторов C/C++ предложили более удобный метод. Они ввели новое ключевое слово `thread`, которое указывает, что переменная является специфичной для потока. Также был разработан новый метод доступа к таким переменным (по крайней мере, на архитектуре i386).  \n\nМетод pthreads обычно реализуется в пользовательском пространстве в виде простой таблицы поиска. Производительность такого решения не очень высока. Новый метод использует (на i386) сегментные регистры для адресации области, где хранится TLS (Thread-Local Storage), так что фактический доступ к переменной потока сводится к добавлению сегментного регистра к адресу, таким образом обращаясь через него. Сегментные регистры, обычно `%gs` и `%fs`, действуют как селекторы сегментов.  \n\nКаждый поток имеет свою собственную область, где хранятся локальные данные потока, и сегмент должен загружаться при каждом переключении контекста. Этот метод очень быстрый и используется практически повсеместно в мире UNIX® на архитектуре i386.  \n\nИ FreeBSD, и Linux® реализуют этот подход, и он даёт очень хорошие результаты. Единственный недостаток — необходимость перезагружать сегмент при каждом переключении контекста, что может замедлять переключения. FreeBSD пытается минимизировать эти накладные расходы, используя только 1 дескриптор сегмента, в то время как Linux® использует 3. Интересно, что почти ничто не использует больше 1 дескриптора (только Wine, кажется, использует 2), поэтому Linux® платит эту необязательную цену при переключении контекстов.",
            "id": 878607,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878607/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1795985/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.658592Z",
            "action": 9,
            "target": "Сегменты на i386",
            "id": 878608,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878608/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1795986/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.673364Z",
            "action": 9,
            "target": "Архитектура i386 реализует так называемые сегменты. Сегмент — это описание области памяти. Он включает базовый адрес (начало) области памяти, её конец (границу), тип, защиту и т.д. Доступ к памяти, описываемой сегментом, может осуществляться с использованием регистров селекторов сегментов (`%cs`, `%ds`, `%ss`, `%es`, `%fs`, `%gs`). Например, предположим, что у нас есть сегмент с базовым адресом 0x1234 и длиной, а также следующий код:",
            "id": 878609,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878609/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1795988/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.688361Z",
            "action": 9,
            "target": "Это загрузит содержимое регистра `%edx` в ячейку памяти по адресу 0x1244. Некоторые сегментные регистры имеют специальное назначение, например, `%cs` используется для сегмента кода, а `%ss` — для сегмента стека, но `%fs` и `%gs` обычно не используются. Сегменты хранятся либо в глобальной таблице GDT, либо в локальной таблице LDT. Доступ к LDT осуществляется через запись в GDT. LDT может хранить больше типов сегментов. LDT может быть отдельной для каждого процесса. Обе таблицы определяют до 8191 записей.",
            "id": 878610,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878610/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1795989/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.702805Z",
            "action": 9,
            "target": "Реализация на Linux(R) i386",
            "id": 878611,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878611/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1795990/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.718265Z",
            "action": 9,
            "target": "Существует два основных способа настройки TLS в Linux(R). Он может быть настроен при клонировании процесса с использованием системного вызова `clone` или с помощью вызова `set_thread_area`. Когда процесс передает флаг `CLONE_SETTLS` в `clone`, ядро ожидает, что память, на которую указывает регистр `%esi`, будет содержать пользовательское представление сегмента в Linux(R), которое преобразуется в машинное представление сегмента и загружается в слот GDT. Слот GDT может быть указан номером или можно использовать -1, что означает, что система сама должна выбрать первый свободный слот. На практике подавляющее большинство программ используют только одну запись TLS и не заботятся о номере записи. Мы используем это в эмуляции и фактически зависим от этого.",
            "id": 878612,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878612/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1795991/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.732936Z",
            "action": 9,
            "target": "Эмуляция Linux(R) TLS",
            "id": 878613,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878613/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1795993/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.752551Z",
            "action": 9,
            "target": "Загрузка TLS для текущего потока происходит путем вызова `set_thread_area`, тогда как загрузка TLS для второго процесса в `clone` выполняется в отдельном блоке в `clone`. Эти две функции очень похожи. Единственное различие заключается в фактической загрузке сегмента GDT, которая происходит при следующем переключении контекста для вновь созданного процесса, в то время как `set_thread_area` должен загрузить его напрямую.  \n\nКод в основном делает следующее. Он копирует дескриптор сегмента в формате Linux(R) из пользовательского пространства. Код проверяет номер дескриптора, но поскольку он различается между FreeBSD и Linux(R), мы немного имитируем его. Мы поддерживаем только индексы 6, 3 и -1. Число 6 — это оригинальный номер Linux(R), 3 — оригинальный номер FreeBSD, а -1 означает авто-выбор. Затем мы устанавливаем номер дескриптора на константу 3 и копируем его обратно в пользовательское пространство. Мы полагаемся на то, что процесс в пользовательском пространстве использует номер из дескриптора, но это работает в большинстве случаев (никогда не встречалось ситуации, когда это не срабатывало), так как процесс в пользовательском пространстве обычно передает 1.  \n\nЗатем мы преобразуем дескриптор из формата Linux(R) в машинно-зависимую форму (т.е. независимую от операционной системы) и копируем его в дескриптор сегмента, определенный FreeBSD. Наконец, мы можем загрузить его. Мы назначаем дескриптор PCB потока (блок управления процессом) и загружаем сегмент `%gs` с помощью `load_gs`. Эта загрузка должна выполняться в критической секции, чтобы ничто не могло нас прервать.  \n\nСлучай `CLONE_SETTLS` работает точно так же, только загрузка с помощью `load_gs` не выполняется. Сегмент, используемый для этого (сегмент номер 3), разделяется между процессами FreeBSD и Linux(R), поэтому слой эмуляции Linux(R) не добавляет накладных расходов по сравнению с обычным FreeBSD.",
            "id": 878614,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878614/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1795995/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.767637Z",
            "action": 9,
            "target": "Реализация amd64 аналогична реализации i386, но изначально не использовался 32-битный дескриптор сегмента для этой цели (поэтому даже нативные пользователи 32-битного TLS не работали), поэтому нам пришлось добавить такой сегмент и реализовать его загрузку при каждом переключении контекста (когда установлен флаг, сигнализирующий о использовании 32-битного режима). Кроме этого, загрузка TLS точно такая же, только номера сегментов отличаются, а формат дескриптора и загрузка немного различаются.",
            "id": 878615,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878615/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1795997/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.782028Z",
            "action": 9,
            "target": "Введение в синхронизацию",
            "id": 878616,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878616/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1795998/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.797955Z",
            "action": 9,
            "target": "Потокам требуется некоторая синхронизация, и POSIX(R) предоставляет несколько её видов: мьютексы для взаимного исключения, блокировки чтения-записи для взаимного исключения с преобладанием операций чтения над записями и условные переменные для сигнализации об изменении состояния. Интересно отметить, что в API потоков POSIX(R) отсутствует поддержка семафоров. Реализации этих механизмов синхронизации сильно зависят от типа поддержки потоков, которая у нас есть. В чистой модели 1:M (пользовательское пространство) реализация может быть выполнена исключительно в пользовательском пространстве и, следовательно, быть очень быстрой (условные переменные, вероятно, будут реализованы с использованием сигналов, т.е. не быстро) и простой. В модели 1:1 ситуация также довольно ясна — потоки должны синхронизироваться с использованием средств ядра (что очень медленно, поскольку требуется выполнение системного вызова). Смешанный сценарий M:N просто комбинирует первый и второй подходы или полагается исключительно на ядро. Синхронизация потоков является важной частью программирования с использованием потоков, и её производительность может значительно влиять на итоговую программу. Недавние тесты в операционной системе FreeBSD показали, что улучшенная реализация `sx_lock` дала 40% прироста скорости в _ZFS_ (активном пользователе `sx`), это внутренние механизмы ядра, но это наглядно демонстрирует, насколько важна производительность примитивов синхронизации.",
            "id": 878617,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878617/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1795999/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.812865Z",
            "action": 9,
            "target": "Многопоточные программы должны быть написаны с минимальной конкуренцией за блокировки. В противном случае, вместо выполнения полезной работы поток просто ожидает блокировку. В результате, наиболее хорошо написанные многопоточные программы демонстрируют низкую конкуренцию за блокировки.",
            "id": 878618,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878618/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796000/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.827690Z",
            "action": 9,
            "target": "Введение в futexes",
            "id": 878619,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878619/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796001/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.842507Z",
            "action": 9,
            "target": "Linux(R) реализует 1:1 потоковую модель, то есть использует примитивы синхронизации в ядре. Как упоминалось ранее, хорошо написанные многопоточные программы имеют низкую конкуренцию за блокировки. Таким образом, типичная последовательность может выполняться как два атомарных увеличения/уменьшения счётчика ссылок мьютекса, что очень быстро, как показано в следующем примере:",
            "id": 878620,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878620/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796003/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.856955Z",
            "action": 9,
            "target": "1:1 threading вынуждает нас выполнять два системных вызова для этих вызовов мьютекса, что очень медленно.",
            "id": 878621,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878621/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796004/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.871716Z",
            "action": 9,
            "target": "Решение, реализованное в Linux(R) 2.6, называется futexes. Futexes выполняют проверку на конкуренцию в пользовательском пространстве и вызывают примитивы ядра только в случае конкуренции. Таким образом, типичный случай обходится без вмешательства ядра. Это обеспечивает достаточно быструю и гибкую реализацию примитивов синхронизации.",
            "id": 878622,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878622/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796006/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.886023Z",
            "action": 9,
            "target": "Системный вызов futex выглядит следующим образом:",
            "id": 878623,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878623/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796008/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.900456Z",
            "action": 9,
            "target": "В этом примере `uaddr` — это адрес мьютекса в пользовательском пространстве, `op` — операция, которую мы собираемся выполнить, а остальные параметры имеют значение, зависящее от конкретной операции.",
            "id": 878624,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878624/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796009/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.914815Z",
            "action": 9,
            "target": "Futexes реализуют следующие операции:",
            "id": 878625,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878625/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796017/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.929585Z",
            "action": 9,
            "target": "Эта операция проверяет, что по адресу `uaddr` записано значение `val`. Если нет, возвращается `EWOULDBLOCK`, в противном случае поток ставится в очередь на futex и приостанавливается. Если аргумент `timeout` не равен нулю, он задает максимальное время ожидания, в противном случае ожидание бесконечно.",
            "id": 878626,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878626/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796019/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.944197Z",
            "action": 9,
            "target": "Эта операция захватывает futex по адресу `uaddr` и пробуждает первые `val` futexов, ожидающих в очереди на этом futex.",
            "id": 878627,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878627/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796021/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.958604Z",
            "action": 9,
            "target": "Эта операция связывает файловый дескриптор с заданным futex.",
            "id": 878628,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878628/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796023/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.973019Z",
            "action": 9,
            "target": "Эта операция берет `val` потоков, ожидающих на futex по адресу `uaddr`, пробуждает их и берет следующие `val2` потоков, перемещая их в очередь futex по адресу `uaddr2`.",
            "id": 878629,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878629/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796025/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:28.987429Z",
            "action": 9,
            "target": "Эта операция делает то же самое, что и `FUTEX_REQUEUE`, но сначала проверяет, что `val3` равно `val`.",
            "id": 878630,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878630/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796027/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:29.002058Z",
            "action": 9,
            "target": "Эта операция выполняет атомарную операцию над `val3` (которая содержит закодированное другое значение) и `uaddr`. Затем она пробуждает `val` потоков на futex по адресу `uaddr`, и если атомарная операция вернула положительное число, пробуждает `val2` потоков на futex по адресу `uaddr2`.",
            "id": 878631,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878631/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796028/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:29.016354Z",
            "action": 9,
            "target": "Реализованные операции в `FUTEX_WAKE_OP`:",
            "id": 878632,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878632/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796034/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:29.030835Z",
            "action": 9,
            "target": "В прототипе futex отсутствует параметр `val2`. Значение `val2` берётся из параметра `struct timespec *timeout` для операций `FUTEX_REQUEUE`, `FUTEX_CMP_REQUEUE` и `FUTEX_WAKE_OP`.",
            "id": 878633,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878633/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796035/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:29.045344Z",
            "action": 9,
            "target": "Эмуляция Futex в FreeBSD",
            "id": 878634,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878634/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796036/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:29.059893Z",
            "action": 9,
            "target": "Эмуляция futex в FreeBSD взята из NetBSD и дополнительно расширена нами. Она размещена в файлах `linux_futex.c` и [.filename]#linux_futex.h#. Структура `futex` выглядит следующим образом:",
            "id": 878635,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878635/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796040/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:29.074240Z",
            "action": 9,
            "target": "И структура `waiting_proc` выглядит следующим образом:",
            "id": 878636,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878636/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796046/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:29.089003Z",
            "action": 9,
            "target": "Фьютекс получается с помощью функции `futex_get`, которая выполняет поиск в линейном списке фьютексов и возвращает найденный или создает новый. При освобождении фьютекса после использования вызывается функция `futex_put`, которая уменьшает счетчик ссылок фьютекса, и если счетчик достигает нуля, фьютекс освобождается.",
            "id": 878637,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878637/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796048/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:29.104063Z",
            "action": 9,
            "target": "Когда futex ставит поток в очередь на ожидание, он создает структуру `working_proc` и помещает эту структуру в список внутри структуры futex, после чего просто выполняет man:tsleep[9] для приостановки потока. Ожидание может быть ограничено по времени. После возврата из man:tsleep[9] (поток был разбужен или истекло время ожидания) структура `working_proc` удаляется из списка и уничтожается. Все это выполняется в функции `futex_sleep`. Если мы были разбужены с помощью `futex_wake`, у нас установлен `wp_new_futex`, поэтому мы ожидаем на нем. Таким образом, фактическое перемещение выполняется в этой функции.",
            "id": 878638,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878638/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796050/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:29.118995Z",
            "action": 9,
            "target": "Пробуждение потока, ожидающего на futex, выполняется в функции `futex_wake`. Сначала в этой функции мы имитируем странное поведение Linux(R), где пробуждаются N потоков для всех операций, за исключением того, что операции REQUEUE выполняются на N+1 потоках. Однако обычно это не имеет значения, так как мы пробуждаем все потоки. Далее в функции в цикле мы пробуждаем n потоков, после чего проверяем, есть ли новый futex для перестановки. Если есть, мы переставляем до n2 потоков на новый futex. Это взаимодействует с `futex_sleep`.",
            "id": 878639,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878639/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796052/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:29.134054Z",
            "action": 9,
            "target": "Операция `FUTEX_WAKE_OP` довольно сложна. Сначала мы получаем два фьютекса по адресам `uaddr` и `uaddr2`, затем выполняем атомарную операцию с использованием `val3` и `uaddr2`. После этого пробуждаются `val` ожидающих на первом фьютексе, и если условие атомарной операции выполняется, мы пробуждаем `val2` (т.е. `timeout`) ожидающих на втором фьютексе.",
            "id": 878640,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878640/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796053/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:29.149341Z",
            "action": 9,
            "target": "futex атомарная операция",
            "id": 878641,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878641/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796054/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:29.165066Z",
            "action": 9,
            "target": "Атомарная операция принимает два параметра `encoded_op` и `uaddr`. Закодированная операция включает саму операцию, сравниваемое значение, аргумент операции и аргумент сравнения. Псевдокод операции выглядит следующим образом:",
            "id": 878642,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878642/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796056/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:29.180582Z",
            "action": 9,
            "target": "И это выполняется атомарно. Сначала происходит копирование числа по адресу `uaddr`, а затем выполняется операция. Код обрабатывает ошибки страниц, и если ошибки не происходит, `oldval` сравнивается с аргументом `cmparg` с помощью компаратора cmp.",
            "id": 878643,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878643/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796057/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:29.195508Z",
            "action": 9,
            "target": "Futex блокировка",
            "id": 878644,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878644/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796058/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:29.210446Z",
            "action": 9,
            "target": "Реализация Futex использует два списка блокировок для защиты `sx_lock` и глобальных блокировок (либо Giant, либо другой `sx_lock`). Каждая операция выполняется заблокированной от начала до самого конца.",
            "id": 878645,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878645/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796059/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:29.225278Z",
            "action": 9,
            "target": "Реализация различных системных вызовов",
            "id": 878646,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878646/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796060/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:29.239951Z",
            "action": 9,
            "target": "В этом разделе я опишу несколько менее значимых системных вызовов, которые стоит упомянуть, потому что их реализация неочевидна или эти вызовы представляют интерес с другой точки зрения.",
            "id": 878647,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878647/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796061/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:29.254591Z",
            "action": 9,
            "target": "*семейство системных вызовов at",
            "id": 878648,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878648/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796062/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:29.270222Z",
            "action": 9,
            "target": "Во время разработки ядра Linux(R) 2.6.16 были добавлены *at-системные вызовы. Эти системные вызовы (например, `openat`) работают точно так же, как их аналоги без at, за исключением параметра `dirfd`. Этот параметр определяет местоположение файла, над которым выполняется системный вызов. Если параметр `filename` является абсолютным, `dirfd` игнорируется, но если путь к файлу относительный, `dirfd` вступает в игру. Параметр `dirfd` представляет собой каталог, относительно которого проверяется относительный путь. Параметр `dirfd` является файловым дескриптором некоторого каталога или `AT_FDCWD`. Например, системный вызов `openat` может выглядеть следующим образом:",
            "id": 878649,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878649/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796065/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:29.285863Z",
            "action": 9,
            "target": "Эта инфраструктура необходима для избежания состояний гонки при открытии файлов вне рабочего каталога. Представьте, что процесс состоит из двух потоков, потока A и потока B. Поток A выполняет `open(./tmp/foo/bah., flags, mode)`, и перед возвратом управления он вытесняется, и начинает выполняться поток B. Поток B не учитывает потребности потока A и переименовывает или удаляет [.filename]#/tmp/foo/#. Возникает состояние гонки. Чтобы избежать этого, мы можем открыть [.filename]#/tmp/foo# и использовать его как `dirfd` для системного вызова `openat`. Это также позволяет пользователю реализовать рабочие каталоги для каждого потока.",
            "id": 878650,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878650/?format=api"
        },
        {
            "unit": "https://translate-dev.freebsd.org/api/units/1796066/?format=api",
            "component": "https://translate-dev.freebsd.org/api/components/documentation/articleslinux-emulation_index/?format=api",
            "translation": "https://translate-dev.freebsd.org/api/translations/documentation/articleslinux-emulation_index/ru/?format=api",
            "user": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "author": "https://translate-dev.freebsd.org/api/users/v.popolitov/?format=api",
            "timestamp": "2025-08-10T20:32:29.300521Z",
            "action": 9,
            "target": "Семейство *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] и простого слоя обёртки.",
            "id": 878651,
            "action_name": "Translation uploaded",
            "url": "https://translate-dev.freebsd.org/api/changes/878651/?format=api"
        }
    ]
}