APE — среда ANSI/POSIX
- Говард Трики
howard@plan9.bell-labs.com
Введение
Среда ANSI/POSIX, сокращенно APE, используется при необходимости портирования большого по размеру или часто-обновляемого программного обеспечения в Plan 9 или из нее. APE — это набор заголовков и объектного кода библиотек, построенных на стандарте ANSI C (ANSI X3.159-1989) и стандарте интерфейса операционных систем POSIX (IEEE 1003.1-1990, ISO 9945-1), POSIX часть описывает основные функции операционной системы. Использование APE влечет низкую скорость компиляции и выполнения кода, так что если импорт или экспорт ПО производится довольно редко и скорость имеет значение, то более приемлемым является использование обычной среды компиляции Plan 9. Другой причиной для использования среды Plan 9 (а не APE) является то, что ее организация заголовков более проста для запоминания и использования.
Существует также некоторые аспекты необходимого поведения POSIX, которые невозможно или очень трудно имитировать в Plan 9. Они описаны ниже. Опыт показывает, что имитирование возможно для большинства программ. Более серьезной проблемой является то, что многие программы используют не предусмотренные в стандарте POSIX функции и заголовки. APE содержит расширения POSIX в этом плане. Для того чтобы среда APE подходила для тестирования программ ANSI/POSIX, расширения должны быть явно описаны в разделе #define.
Pcc
Команда pcc работает как внешняя для компиляторов и загрузчиков Plan 9 C. Она запускает препроцессор ANSI C для исходных файлов, используя заголовки APE для определения директив #include <файл>; затем она запускает компилятор Plan 9 C; и наконец, она загружается с APE библиотеками для создания исполняемой программы. Документ «Как использовать компилятор Plan 9 C» (How to Use the Plan 9 C Compiler, /sys/doc/comp.ps) объясняет как переменные окружения используются при компиляции на различных архитектурах. Переменная окружения $objtype управляет тем, какой Plan 9 компилятор и загрузчик используются pcc, также как и размещение файлов заголовков и библиотек. Например, если переменная $objtype имеет значение mips, тогда pcc указывает cpp искать заголовки в каталоге /mips/include/ape, следующим после /sys/include/ape; затем pcc использует vc для создания объектных файлов с расширением .v; и наконец, vl используется для создания исполняемого кода с использованием библиотек из каталога /mips/lib/ape.
Psh и Cc
Команда pcc предназначена для просмотра исходного кода на наличие ANSI/POSIX, но сами программы постраиваются обычным для Plan 9 способом: посредством mk и созданием объектных файлов с именами, заканчивающимися расширением .v, и т.п. Но иногда бывает полезнее использовать программы POSIX make и cc (который создает объектные файлы с именами, заканчивающимися .o, а также автоматически вызывает загрузчик, если опция -c не указана). В таком случае, выполните следующую команду:
ape/psh
Она запускает POSIX оболочку со средой, включающей POSIX команды: ar89, c89, cc, basename, dirname, expr, false, grep, kill, make, rmdir, sed, sh, stty, true, uname, и yacc. Также есть несколько метка-заполнителей для команд, которые не предусмотрены в Plan 9: chown, ln и umask.
Команда cc обладает опциями POSIX c89, определенными в C-Language Development Utilities Option, приложении стандарта POSIX Shell and Utilities. Также существуют несколько нестандартных опций, описанных ниже:
- -v для эхо контроля команд при каждой передаче на stdout;
- -A для включения прототипа предупреждений ANSI;
- -S для вывода языка ассемблера в файл.s;
- -Wp,арг-ы для передачи аргументов арг-ы в cpp;
- -W0,арг-ы для передачи арг-ы в 2c, и т.п.;
- и опция -Wl,арг-ы для передачи аргументов арг-ы в 2l, и т.д. и т.п.
Команда sh является оболочкой pdksh, наиболее распространенной и уступчивой POSIX версией Korn Shell. Реализация Plan 9 не содержит режимов редактирования emacs и vi.
Команда stty эффективна лишь в том случае, если команда ape/ptyfs запущена для вставки псевдо-tty интерфейса между /dev/cons и запущенной командой. Ни одна распространяемая команда не делает этого автоматически.
Символы
Стандарты C и POSIX требуют, чтобы определенные символы описывались в заголовках. Описание (или не описание) зависит от типа самих символов и усмотрения реализации. POSIX описывает макросы (макроопределения), которые также являются символами препроцессора, начинающимися с символа подчеркивания и с далее идущими буквами в верхнем регистре; если программа, описанная в разделе #defines, является макросом, то перед включением каких-либо заголовков она посылает запрос на то, чтобы определенные символы были видимыми в заголовках. Наиболее важным макросом является _POSIX_SOURCE: символы, характерные POSIX, становятся видимыми в соответствующих заголовках. Рассмотрим этот факт на примере: ANSI определяет некоторые имена, которые должны быть описаны, но POSIX, в свою очередь, определяет другие имена, такие как sigset_t, которые не допускаются согласно ANSI. Эта проблема решается созданием дополнительных символов видимыми только когда определен макрос _POSIX_SOURCE.
При экспорте программ он помогает установить, входит ли программа в одну из следующих категорий:
- Строго соответствующая программа ANSI C. Ею используются лишь характеристики языка, библиотек и заголовков, соответствующие стандарту C. Она не зависит от неопределенного, неописанного, или зависимого от реализации поведения, и не превышает любой минимальный предел реализации.
- Строго соответствующая программа POSIX. Аналогична вышеописанной, только для стандарта POSIX.
- Усовершенствованный набор POSIX с расширениями. Каждое расширение выбирается макросом, так что ясно какие расширения здесь используются.
Что касается обезьяны, тьфу, то есть APE, если заголовки всегда включают объявления любых используемых библиотечных функций, то набор макросов, описанный в программе, будет указывать к какой из вышеперечисленных категорий относится программа. Чтобы выполнить это, символы, не соответствующие стандарту C или POSIX не должны описываться в заголовке, а те которые принадлежат стандарту POSIX должны защищаться макросом #ifdef _POSIX_SOURCE. К примеру, определения EDOM, ERANGE, и errno соответствуют стандарту C. Стандарт C допускает больше имен, начинающихся с буквы E, но наш заголовок описывает все макросы, отличные от _POSIX_SOURCE, в этом случае символы, требующиеся POSIX, также определяются. Это значит, что программа, использующая ENAMETOOLONG, не может замаскироваться под строго соответствующую программу ANSI C.
Pcc и cc не могут определять никакие препроцессоры, отличные от 5 встроенных в стандарт ANSI C: __STDC__, __LINE__, __FILE__, __DATE__, и __TIME__ . Любые другие должны определять себе в программе или, используя опцию -D, в командной строке.
Расширения
Операция, осуществляемая вставкой только необходимых имен в заголовки, полезна при экспорте программ, но она несколько мешает при импорте программ. Компромиссом может быть учитывание дополнительных символов в заголовках, дополнительных заголовках, и дополнительных библиотечных функциях, но только под управлением расширенных макросов. Следующие расширения предусмотрены; если они не указаны явно, то дополнительные библиотечные функции предусмотрены в библиотеке APE по умолчанию.
- _LIBG_EXTENSION. Разрешает использование графической библиотеки Plan 9 (функции описаны в man-странице graphics(2)) за исключением того, что div должен быть переименован в ptdiv. Заголовок объявления необходимых типов и функций также включаем.
- _LIMITS_EXTENSION. POSIX не требует определения имен типа PATH_MAX и OPEN_MAX, но многие программы принимают так, будто бы они определены там. Если макрос _LIMITS_EXTENSION определен, то все те имена должны включаться с определениями.
- _BSD_EXTENSION. Это расширение включается не только в программы Berkeley Unix, но также и в большинство других смешанных программ, часто находящихся в составе других реализациях Unix. Расширение допускает включение любой из функций: для bcopy(), bcmp(), и др. из Berkeley; для gethostbyname(), и подобных ей связанных структур; для функции Berkeley select и связанных типов и макросов для работы с многочисленными входными источниками; <sys/ioctl.h> для функции ioctl (минимально реализованной); <sys/param.h> для NOFILES_MAX; <sys/pty.h> для поддержки псевдо-tty, посредством функций ptsname(int) и ptmname(int); <sys/resource.h>; <sys/socket.h> для сокетных структур, констант и функций; <sys/time.h> для определения структур timeval и timezone; и <sys/uio.h> для структуры iovec и функций writev и readv, используемых для разброса/сборки ввода-вывода. Определение макроса _BSD_EXTENSION также допускает различные экстра расширения в <ctype.h>, <signal.h>, <stdio.h>, <unistd.h>, <sys/stat.h>, и <sys/times.h>.
- _NET_EXTENSION. Разрешает включения, определяющие сетевые функции. Они описаны в man-странице dial(2).
- _REGEXP_EXTENSION. Разрешает включения, определяющие функции соответствия регулярных выражений. Они описаны в man-странице regexp(2).
- _RESEARCH_SOURCE. Расширение позволяет использовать небольшую библиотеку функций из десятой версии Unix (V10). Эти функции и типы необходимо использовать путем определения в заголовке. Предусмотренные функции: srand, rand, nrand, lrand и frand (улучшенные генераторы случайных чисел); getpass, tty_echoon, tty_echooff (для работы с терминальными характеристиками ); min and max; nap; и setfields, getfields, и getmfields (для синтаксического анализа строк в полях). Смотрите руководство программиста десятой версии Unix за детальным описанием всех этих функций.
Общие проблемы
Несколько больших систем, включая X11, были удачно портированы в Plan 9 с использованием APE (порт X11 не включается в основной дистрибутив Plan 9, поскольку для его поддержки нужно слишком много работы). Проблемы можно разделить на три основные категории: (1) используются характеристики не ANSI C/POSIX; (2) неадекватное имитирование POSIX функций; и (3) дефекты компилятора/загрузчика. Наибольшее количество проблем возникает в первой категории.
В данный момент POSIX только становится мишенью для программистов. Большая часть существующего кода написана для работы с одной из систем (или с обоими) BSD или System V Unix. Последняя довольно близка к POSIX, но, все-же, есть и некоторые различия. Также множество System V систем импортировали некоторые характеристики BSD, которые не являются частью POSIX. Хорошей стратегией портирования внешних программ является использование макроса CFLAGS=-D_POSIX_SOURCE; если это не работает, попробуйте добавить _D_BSD_EXTENSION а также включите <bsd.h> в исходные файлы. Вот некоторые решения проблем, которые могли остаться:
- Третий (окружение) аргумент к main. Взамен используйте глобальный environ.
- OPEN_MAX, PATH_MAX, и т.п., принятые в <limits.h>. Перепишите для вызова sysconf или определите _LIMITS_EXTENSION.
- <varargs.h>. Перепишите для использования <stdarg.h>.
Неадекватность имитирования POSIX функций в Plan 9. Этот недостаток редко происходит (кроме случаев проблем с link), но, все-же, мы их опишем:
- Функции установки идентификатора пользователя, группы, эффективного идентификатора пользователя, эффективного идентификатора группы — не делают ничего полезного. Эту концепцию трудно имитировать в Plan 9. Chown также бесполезен.
- execlp и связанные с ней функции не просматривают значение переменной окружения PATH. В случае, если путевое имя программы не абсолютное, тогда они делают попытку в текущем каталоге и в каталоге /bin.
- Консультативная блокировка через fcntl не осуществима.
- Трудно заставить работать корректно isatty. Использованная аппроксимация только иногда правильна.
- link неработоспособен.
- Вместе с open, опция O_NOCTTY не имеет эффекта. Понятие управления tty чуждо Plan 9.
- setsid разделяет пространство имен и группу примечаний, только условно ведет себя правильно.
- Функции работы со стекингом сигналов, sigpending, sigprocmask и sigsuspend — не работают.
- Umask не работает, так как такого понятия нет в Plan 9.
- Код, в котором есть вызов getenv("HOME") должен быть изменен на getenv("home") в Plan 9.
Copyright © 2000 Lucent
Technologies Inc. All rights reserved.
Copyright © 2003 Перевод Андрей С. Кухар.