[Системное администрирование, *nix, Разработка под Linux] Заметки о Unix: надёжная работа с API C-библиотеки Unix возможна только из программ, написанных на C (перевод)

Автор Сообщение
news_bot ®

Стаж: 6 лет 3 месяца
Сообщений: 27286

Создавать темы news_bot ® написал(а)
14-Май-2021 22:32

Для того чтобы полностью реализовать требования системы верификации источника системных вызовов, разработчики OpenBSD хотят, чтобы Go выполнял бы системные вызовы через C-библиотеку, а не напрямую, из собственной среды выполнения (а у Go есть некоторые причины поступать именно так). На первый взгляд это кажется не особенно серьёзной проблемой. Это, конечно, немного неудобно, но у языка вроде Go должна быть возможность просто выполнять вызовы обычных функций из C-библиотеки, вроде open() (и использовать ABI вызова C-функций). К сожалению, не так всё просто, так как очень часто фрагменты обычного API C-библиотеки, на самом деле, реализованы в препроцессоре C. Из-за этого API C-библиотеки нельзя надёжно использовать для решения обычных задач без написания собственного связующего кода на C.

оригинал
Звучит это, пожалуй, дико, поэтому позвольте мне проиллюстрировать это на примере всеми любимого значения errno, к которому обращаются для получения кода ошибки в том случае, если системный вызов даёт сбой (им же пользуются и для получения кодов ошибок от некоторых библиотечных вызовов). В этом материале я рассказывал о том, что в современных условиях механизм errno должен быть реализован так, чтобы у разных потоков были бы разные значения errno, так как они могут в одно и то же время выполнять различные системные вызовы. Это требует наличия у потоков собственных локальных хранилищ, а к такому хранилищу нельзя обратиться так же, как к простой переменной. Доступ к нему должен быть организован через специальный механизм, поддерживаемый средой выполнения C. Вот объявления errno из OpenBSD 6.6 и из текущей версии Fedora Linux с glibc:
/* OpenBSD */
int *__errno(void);
#define errno (*__errno())
/* Fedora glibc */
extern int *__errno_location (void) __THROW __attribute_const__;
# define errno (*__errno_location ())

В обоих этих случаях переменная errno, на самом деле, представлена определением препроцессора. Это определение ссылается на внутренние недокументированные функции C-библиотеки (на что указывают два символа подчёркивания в их именах), которые не входят в состав общедоступного API. Если скомпилировать код, написанный на C, рассчитанный на работу с этим API errno (включив в код errno.h), то он будет работать, но это — единственный официальный способ работы с errno. Нет некоей обычной переменной errno, которую можно загрузить в среде выполнения своего языка, например, после вызова функции open(). А если вызвать __errno или ____errno_location в своей среде выполнения, то это будет означать использование внутреннего API, который в будущем вполне может измениться (хотя он, вероятно, не изменится). Для того чтобы создавать надёжные среды выполнения языков программирования, которые ориентированы на общедоступный API С-библиотеки, недостаточно просто вызвать экспортированную функцию вроде open(); нужно ещё написать и скомпилировать собственную маленькую C-функцию, которая просто возвращает среде выполнения errno.
(Тут, помимо errno, могут быть и другие важные моменты; я предлагаю самостоятельно поискать их тем, кому интересна эта тема.)
Это, конечно, не какая-то новая проблема Unix. С первых дней stdio в V7 некоторые из «функций» stdio были реализованы в stdio.h в виде макросов препроцессора. Но в течение долгого времени никто не настаивал на том, чтобы единственным официально поддерживаемым способом выполнения системных вызовов было бы их выполнение из C-библиотеки, что позволяло обойти нечто вроде того, что представляет собой современный механизм errno, в тех случаях, когда не нужна совместимость с C-кодом.
(До того, как в Unix появилась многопоточность, сущность errno была представлена простой переменной и, в целом, выглядела как хороший, хотя и не идеальный интерфейс.)
Пользовались ли вы когда-нибудь недокументированными API?

оригинал

оригинал
===========
Источник:
habr.com
===========

===========
Автор оригинала: Chris Siebenmann
===========
Похожие новости: Теги для поиска: #_sistemnoe_administrirovanie (Системное администрирование), #_*nix, #_razrabotka_pod_linux (Разработка под Linux), #_unix, #_sistemnoe_administrirovanie (системное администрирование), #_ruvds_perevod (ruvds_перевод), #_blog_kompanii_ruvds.com (
Блог компании RUVDS.com
)
, #_sistemnoe_administrirovanie (
Системное администрирование
)
, #_*nix, #_razrabotka_pod_linux (
Разработка под Linux
)
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 21-Май 20:47
Часовой пояс: UTC + 5