Реализация функций API с помощью внешних библиотек

При реализации функций API с помощью внешних библиотек эти функции пре­доставляются пользователю в виде библиотеки процедур и функций, созданной сторонним разработчиком.

Система программирования ответственна только за то, чтобы подключить объект­ный код библиотеки к результирующей программе. Причем внешняя библиотека может быть и динамически загружаемой (загружаемой во время выполнения про­граммы).

С точки зрения эффективности выполнения этот метод реализации API имеет са­мые низкие результаты, поскольку внешняя библиотека обращается как к функ­циям операционной системы, так и к функциям RTL языка программирования. Только при очень высоком качестве внешней библиотеки ее эффективность срав­нима с эффективностью библиотеки RTL.

Если говорить о переносимости исходного кода, то здесь требование только одно — используемая внешняя библиотека должна быть доступна в любой из архитектур вычислительных систем, на которые ориентирована прикладная программа. Тог­да удается достигнуть переносимости. Это возможно, если внешняя библиотека удовлетворяет какому-то принятому стандарту, а система программирования под­держивает этот стандарт.

Например, библиотеки, удовлетворяющие стандарту POSIX (см. следующий раз­дел), доступны в большинстве систем программирования для языка С. И если при­кладная программа использует только библиотеки этого стандарта, то ее исход­ный код будет переносимым. Еще одним примером является широко известная библиотека графического интерфейса XLib, поддерживающая стандарт графичес­кой среды X-Window.

Для большинства специфических библиотек отдельных разработчиков это не так. Если пользователь использует какую-то библиотеку, то она ориентирована на ог-

Реализация функций API с помощью внешних библиотек - student2.ru Интерфейс прикладного программирования_______________________________ 303

раниченный набор доступных архитектур целевой вычислительной системы. При­мерами могут служить библиотеки MFC (Microsoft Foundation Classes) от Microsoft и VCL (Visual Controls Library) от Borland, жестко ориентированные на архитек­туру операционных систем семейства Windows.

Тем не менее многие фирмы-разработчики сейчас стремятся создавать библиоте­ки, которые бы обеспечивали переносимость исходного кода приложений между различными архитектурами целевой вычислительной системы. Пока еще такие библиотеки не получили широкого распространения, но имеется несколько попы­ток их реализации, например библиотека CLX от Borland ориентирована на архи­тектуру операционных систем семейств Linux и Windows.

В целом развитие функций API идет в направлении попытки создать библиотеки API, обеспечивающие широкую переносимость исходного кода. Однако с учетом корпоративных интересов различных производителей и сложившейся ситуации на рынке в ближайшее время вряд ли удастся достичь значительных успехов в этом направлении. Разработка широко применимого стандарта API пока еще остается делом будущего.

Поэтому разработчики системных программ вынуждены оставаться в довольно узких рамках ограничений стандартных библиотек языков программирования.

Что касается прикладных программ, то гораздо большую перспективу для них пре­доставляют технологии, связанные с разработками в рамках архитектуры клиент-сервер или трехзвенной архитектуры создания приложений. В этом направлении ведущие производители операционных систем, СУБД и систем программирова­ния скорее достигнут соглашений, чем в направлении стандартизации API.

Итак, нами были рассмотрены основные принципы, цели и подходы к реализации системных интерфейсов API. Отметим еще один очень важный момент: желатель­но, чтобы интерфейс прикладного программирования не зависел от системы про­граммирования. Конечно, были одно время персональные компьютеры, у которых базовой системой программирования выступал интерпретатор с языка Basic, но это скорее исключение. Обычно интерфейс API не зависит от системы програм­мирования и может вызываться из любой системы программирования, хотя и с ис­пользованием соответствующих правил построения вызывающих последователь­ностей. В то же время, в ряде случаев система программирования может сама генерировать обращения к API. Например, мы можем написать в программе вызов функции по запросу 256 байт памяти:

unsigned char * ptr = malloc (256);

Система программирования с языка С сгенерирует целую последовательность об­ращений. Из кода пользовательской программы будет осуществлен вызов библио­течной функции malloc, код которой расположен в RTL языка С. Библиотека вре­мени выполнения, в данном случае, реализует вызов malloc уже как вызов системной функции HeapAlloc API:

LPVOID НеарAlloc(

HANDLE hHeap. // handle to the private heap block - указатель на блок DWORD dwFlags, // heap allocation control flags - свойства блока

Реализация функций API с помощью внешних библиотек - student2.ru 304______________________________ Глава 9 Архитектура операционных систем

DWORD dwBytes // number of bytes to allocate - размер блока ):

Параметры выделяемого блока памяти в таком случае задаются системой програм­мирования, и пользователь лишен возможности задавать их напрямую. С другой стороны, если это необходимо, функции API можно вызывать прямо в тексте про­граммы:

unsigned char * ptr - (LPVOID) HeapAllocC GetProcessHeapO, 0, 256); В этом случае программирование вызова немного усложняется, но получаемый конечный результат будет, как правило, короче и, что самое важное, работать бу­дет эффективнее. Следует отметить, что далеко не все возможности API доступны через обращения к функциям системы программирования. Непосредственное об­ращение к API позволяет пользователю обращаться к системным ресурсам более эффективным способом. Однако это требует знания функций API, количество ко­торых нередко достигает нескольких сотен.

Как правило, функции API не стандартизированы. В каждом конкретном случае набор вызовов API определяется, прежде всего, архитектурой операционной сис­темы и ее назначением. В то же время, принимаются попытки стандартизировать некоторый базовый набор функций, поскольку это существенно облегчило бы пе­ренос приложений с одной операционной системы на другую. Таким примером может служить очень известный и, пожалуй, один из самых распространенных стан­дарт POSIX. В этом стандарте перечислен большой набор функций, их парамет­ров и возвращаемых значений. Стандартизированными, согласно POSIX, являют­ся не только обращения к API, но и файловая система, организация доступа к внешним устройствам, набор системных команд'. Использование в приложениях этого стандарта позволяет в дальнейшем легко переносить такие программы с од­ной операционной системы в другую путем простейшей перекомпиляции исход­ного текста.

Частным случаем попытки стандартизации API является внутренний корпоратив­ный стандарт компании Microsoft, известный как WinAPI. Он включает в себя сле­дующие реализации: Win 16, Win32s, Win32, WinCE. С точки зрения WinAPI (в силу ряда идеологических причин графический, то есть «оконный», интерфейс пользователя обязателен) базовой задачей является окно. Таким образом, стан­дарт WinAPI изначально ориентирован на работу в графической среде. Однако базовые понятия дополнены традиционными функциями, в том числе частично поддерживается стандарт POSIX.

Интерфейс POSIX

POSIX (Portable Operating System Interface for Computer Environments — незави­симый от платформы системный интерфейс для компьютерного окружения) — это стандарт IEEE (Institute of Electrical and Electronics Engineers — институт инже­неров по электротехнике и радиоэлектронике), описывающий системные интер-

Реализация функций API с помощью внешних библиотек - student2.ru ' В данном контексте под системными командами следует понимать некий набор программ, позволя­ющих управлять вычислительными процессами, например pstat, kill, dir и др.

Реализация функций API с помощью внешних библиотек - student2.ru Интерфейс POSIX___________________________________________________ 305

фейсы для открытых операционных систем, в том числе оболочки, утилиты и ин­струментарии. Помимо этого, согласно POSIX, стандартизированными являются задачи обеспечения безопасности, задачи реального времени, процессы админист­рирования, сетевые функции и обработка транзакций. Стандарт базируется на UNIX-системах, но допускает реализацию и в Других операционных системах.

Интерфейс POSIX начинался как попытка пропаганды институтом IEEE идей переносимости приложений в UNIX-средах путем разработки абстрактного неза­висимого от платформы стандарта. Однако POSIX не ограничивается только UNIX-системами; существуют различные реализации этого стандарта в системах, которые соответствуют требованиям, предъявляемым стандартом IEEE Standard 1003.1-1990 (POSIX. 1). Например, известная ОС реального времени QNX соответствует спецификациям этого стандарта, что облегчает перенос приложений в эту систе­му, но UNIX-системой не является ни в каком виде, ибо ее архитектура использу­ет абсолютно иные принципы.

Этот стандарт подробно описывает систему виртуальной памяти (Virtual Memory System, VMS), многозадачность (Multiprocess Executing, МРЕ) и технологию пе­реноса операционных систем (CTOS). Таким образом, на самом деле POSIX пред­ставляет собой множество стандартов POSIX. 1-POSIX. 12. В табл. 9.1 перечисле­ны основные направления, описываемые данными стандартами. Следует также особо отметить, что в POSIX. 1 основным языком описания системных функций API предполагается язык С.

Таблица 9.1. Семейство стандартов POSIX

Реализация функций API с помощью внешних библиотек - student2.ru Стандарт Стандарт ISO Краткое описание

Реализация функций API с помощью внешних библиотек - student2.ru POSIX.0 Нет Введение в стандарт открытых систем. Данный документ

не является стандартом в чистом виде, а представляет собой рекомендации и краткий обзор технологий

POSIX.1 Да Системный интерфейс API (язык С)

POSIX.2 Нет Оболочки и утилиты (одобренные IEEE)

POSIX.3 Нет Тестирование и верификация

POSIX.4 Нет Задачи реального времени и потоки выполнения

POSIX.5 Да Использование языка ADA применительно

к стандарту POSIX. 1

POSIX.6 Нет Системная безопасность

POSIX.7 Нет Администрирование системы

POSIX.8 Нет Сети, «прозрачный» доступ к файлам, абстрактные

сетевые интерфейсы, не зависящие от физических протоколов, вызовы RPC, связь системы с приложениями, зависящими от протокола

POSIX.9 Да Использование языка Fortran, применительно

к стандарту POSIX. 1

POSIX. 10 Нет Super-computing Application Environment Profile (AEP)

POSIX. 11 Нет Обработка транзакций AEP

POSIX. 12 Нет Графический интерфейс пользователя (GUI)

Реализация функций API с помощью внешних библиотек - student2.ru 306______________________________ Глава 9. Архитектура операционных систем

Таким образом, программы, написанные с соблюдением данных стандартов, бу­дут одинаково выполняться на всех POSIX-совместимых системах. Однако стан­дарты отчасти носят всего лишь рекомендательный характер. Часть стандартов описана очень строго, тогда как другая часть только поверхностно раскрывает основные требования. Нередко программные системы заявляются как POSIX-совместимые, хотя таковыми их назвать нельзя. Причины кроются в формальном подходе к реализации интерфейса POSIX в различных операционных системах. На рис. 9.1 изображена типовая схема реализации строго соответствующего POSIX приложения.

Реализация функций API с помощью внешних библиотек - student2.ru

Рис. 9.1. Схема реализации приложения, строго соответствующего стандарту POSIX

Из рисунка видно, что для взаимодействия с операционной системой программа использует только библиотеки POSIX. 1 и стандартную библиотеку RTL языка С, в которой возможно использование только 110 различных функций, также опи­санных стандартом POSIX. 1.

К сожалению, достаточно часто с целью увеличения производительности той или иной подсистемы либо для введения фирменных технологий, которые ограни­чивают область применения приложения соответствующей операционной сре­дой, при программировании используются другие функции, не отвечающие стан­дарту POSIX.

Реализации стандарта POSIX на уровне операционной системы различны. Если UNIX-системы в своем абсолютном большинстве изначально соответствуют спецификациям IEEE Standard 1003.1-1990, то WinAPI не является POSIX-совместимым. Однако для его поддержки в операционной системе Windows NT введен специальный модуль API для поддержки стандарта POSIX, работаю­щий на уровне привилегий пользовательских процессов. Данный модуль обес­печивает преобразование и передачу вызовов из пользовательской программы к ядру системы и обратно, работая с ядром через WinAPI. Прочие приложения, написанные с использованием WinAPI, могут передавать информацию POSIX приложениям через стандартные механизмы потоков ввода-вывода stdin и stdout [57].

Реализация функций API с помощью внешних библиотек - student2.ru Примеры программирования для разных интерфейсов API____________________ 307

Примеры программирования для разных интерфейсов API

Для наглядной демонстрации принципиальных различий интерфейсов API наи­более популярных современных операционных систем для персональных ком­пьютеров рассмотрим простейший пример, в котором необходимо подсчитать количество пробелов в текстовых файлах, имена которых должны указываться в ко­мандной строке. Рассмотрим два варианта программы: для Windows (с использо­ванием WinAPI) и для Linux (POSIX API).

Поскольку нас интересует работа с параллельными задачами, пусть при выполне­нии программы для каждого из перечисленных в командной строке файлов созда­ется свой процесс или поток выполнения (задача), который параллельно с други­ми процессами (потоками) производит работу по подсчету пробелов в «своем» файле. Результатом работы программы будет являться список файлов с подсчи­танным количеством пробелов для каждого.

Следует обратить особое внимание на то, что приведенные ниже реализации про­грамм решения данной задачи не являются единственно возможными. В обеих рассматриваемых операционных системах существуют разные методы работы с файловой системой и управления процессами. В данном случае рассматривается только один, но наиболее характерный для соответствующего интерфейса API ва­риант.

Для того чтобы было удобнее сравнивать эту (листинг 9.1) и следующую (лис­тинг 9.2) программы, а также учитывая, что задача не требует для своего решения оконного интерфейса, в тексте использованы только те вызовы API, которые не затрагивают графический интерфейс. Конечно, нынче редко какое приложение не использует возможностей GUI, но зато в нашем случае сразу можно увидеть раз­ницу в организации параллельной работы запускаемых вычислений.

Листинг 9.1. Текст программы для Windows (WinAPI)

#include <windows.h> .#include <stdio.h> #include <stdlib.h>

// Название: processFile

// Описание: исполняемый код потока

// Входные параметры: lpFileName - имя файла для обработки

// Выходные параметры: нет

DWORD processFile(LPVOID lpFileName ) {

HANDLE handle; // описатель файла

DWORD numRead, total = 0:

char buf;

// запрос к ОС на открытие файла (только для чтения) handle = CreateFileC (LPCTSTR)lpFileName. GENERIC_READ, FILE_SHARE_READ, NULL. OPENJXISTING, FILE_ATTRIBUTE_NORMAL. NULL):

// цикл чтения до конца файла

do { продолжение

Реализация функций API с помощью внешних библиотек - student2.ru 308_____________________________ Глава 9. Архитектура операционных систем

Листинг 9.1(продолжение)

II чтение одного символа из файла ReadFile( handle, (LPVOID) &buf, 1. &numRead, NULL); if (buf == 0x20) total++: } while ( numRead > 0);

fprintf( stderr. "(ThreadID: %Lu), File %s. spaces - %d\n". GetCurrentThreadldC). lpFi1eName, total);

// закрытие файла CloseHandle( handle);

return(O); }

// Название: main

// Описание: главная программа

// Входные параметры: список имен файлов для обработки

// Выходные параметры: нет

int main(int argc, char *argv[]) {

int i:

DWORD pid;

HANDLE hThrd[255]; // массив ссылок на потоки

// для всех файлов. перечисленных в командной строке for (i = 0; i< (argc-1): i++) {

// запуск потока - обработка одного файла hThrd[i] = CreateThread( NULL. 0x4000. (LPTHREAD_START_ROUTINE) processFile. (LPVOID) argv[i+l]. 0. &pid);

fprintf( stdout, "processFile started (HND-%d)\n", hThrd[i]); }

// ожидание окончания выполнения всех запущенных потоков WaitFortlultipleObjects( argc-1. hThrd, true. INFINITE);

return(O); }

Обратите внимание, что основная программа запускает потоки и ждет окончания их выполнения. Другими словами, мы имеем всего один вычислительный процесс, но используем мультизадачные возможности операционной системы.

Листинг 9.2.Текст программы для Linux (POSIX API)

#include <sys/types.h>

#include <sys/stat.h>

#include <wait.h>

#include <fcntl,h>

#include <stdio.h>

// Название: processFile

// Описание: обработка файла, подсчет кол-ва пробелов // Входные параметры: fileName - имя файла для обработки // Выходные параметры: кол-во пробелов в файле int processFile( char *fileName) { int handle, numRead. total = 0:

Реализация функций API с помощью внешних библиотек - student2.ru Примеры программирования для разных интерфейсов API_________________ 309

char buf;

// запрос к ОС на открытие файла (только для чтения) handle = open( fileName. O_RDONLY);

// цикл чтения до конца файла do {

// чтение одного символа из файла

numRead = read( handle. &buf, 1);

if (buf == 0x20) total++: } while (numRead > 0):

// закрытие файла closet handle); return( total); }

// Название: main

// Описание: главная программа

// Входные параметры: список имен файлов для обработки

// Выходные параметры: нет

int main(int argc. char *argv[]) {

int i. pid, status;

// для всех файлов, перечисленных в командной строке for (i = 1: i< argc; i++) {

// запускаем дочерний процесс pid = fork(); if (pid — 0) {

// если выполняется дочерний процесс

// вызов функции счета количества пробелов в файле

printfC "(PID: %в). File %s, spaces = %d\n".

getpidO, argv[ i], processFile( argv[ i])); // выход из процесса exitO;

}

// если выполняется родительский процесс else

printfC"processFile started (pid=%d)\n". pid); }

// ожидание окончания выполнения всех запущенных процессов

if (pid != 0) while (wait(&status)>0):

return; }

Из листинга 9.2 видно, что здесь все вычисления имеют статус процессов, а не по­токов выполнения. Надо заметить, что многие современные версии UNIX поддер­живают механизм потоков, поскольку потоки в ряде случаев позволяют повысить эффективность вычислений и упрощают их создание, но в рассматриваемом ин­терфейсе потоков нет.

В заключение можно заметить, что очень трудно сравнивать интерфейсы API. При их разработке создатели, как правило, стараются реализовать функционально пол­ный набор основных функций, используя которые можно решать разные задачи, правда, порой, различными способами. Один набор системных функций хорош для

Реализация функций API с помощью внешних библиотек - student2.ru Реализация функций API с помощью внешних библиотек - student2.ru 310______________________________ Глава 9. Архитектура операционных систем

одного набора задач, другой — для иного набора задач. Тем более что, фактически, сейчас мы имеем существенно ограниченное множество интерфейсов API из-за того, что имеет место доминирование наиболее популярных операционных сис­тем и на их распространении в большей степени сказалась правильная маркетин­говая политика их создателей, а не достоинства и недостатки самих этих систем и их интерфейсов.

Контрольные вопросы и задачи

1. Что вы понимаете под архитектурой операционной системы?

2. Перечислите и поясните основные принципы построения операционных сис­
тем.

3. Для чего операционные системы используют несколько режимов работы про­
цессора? Чем отличается супервизорный режим работы процессора от пользо­
вательского? Как часто процессор переводится в супервизорный режим?

4. Объясните принцип виртуализации. Имеется ли связь между принципом вир­
туализации и принципом совместимости? Если имеется, то поясните, в чем
она заключается?

5. Что такое ядро операционной системы? Расскажите об основных моментах,
характерных для микроядерных ОС. Какие основные функции должно вы­
полнять микроядро ОС?

6. Перечислите основные требования, предъявляемые к операционным систе­
мам в плане обеспечения информационной безопасности.

7. Перечислите основные требования, предъявляемые к операционным систе­
мам реального времени.

8. Какие задачи возлагаются на интерфейс прикладного программирования (API)?

9. Какими могут быть варианты реализации API? В чем заключаются достоин­
ства и недостатки каждого варианта?

10. Что такое библиотека времени выполнения (RTL)?

11. Что такое POSIX? Какими преимуществами обладают программы, созданные
с использованием только стандартных функций, предусмотренных POSIX?

Реализация функций API с помощью внешних библиотек - student2.ru Глава 10. Краткий обзор современных операционных систем

Теперь, после знакомства с основными понятиями, относящимися к операцион­ным системам, и изучения конкретных механизмов, реализующих известные ме­тоды организации вычислительных процессов, вкратце рассмотрим архитектурные особенности современных операционных систем для персональных компьютеров типа IBM PC.

Прежде всего, отметим тот общеизвестный факт, что наиболее популярными являются операционные системы семейства Windows компании Microsoft. Это и Windows 95/98/МЕ, и Windows NT/2000, и новое поколение Windows XP/ 2003 — этим операционным системам посвящена отдельная глава (см. главу 11). Здесь же мы рассмотрим операционные системы, не относящиеся к продуктам Microsoft, — это UNIX-подобные операционные системы Linux и FreeBSD, a также системы QNX и OS/2. При изучении известных всему миру систем с об­щим названием Linux и системы FreeBSD, по которым сейчас появляется не­мало монографий и учебников, упор будет сделан именно на основных архи­тектурных особенностях семейства UNIX, в абсолютном своем большинстве относящихся ко всем UNIX-системам. Система QNX была выбрана потому, что является наиболее известной и удачной операционной системой реального вре­мени. Операционную систему OS/2 мы рассмотрим последней. Хотя сейчас эта система уже практически всеми забыта1, она была одной из первых полноцен­ных и надежных мультипрограммных и мультизадачных операционных систем для персональных компьютеров, в которой поддерживалось несколько опера­ционных сред.

Реализация функций API с помощью внешних библиотек - student2.ru ' В настоящее время ее используют те организации, которые в свое время создали под нее свои прило­жения, вложив немалые средства. И поскольку система по-прежнему в основном неплохо выполня­ет свои функции, эти организации не спешат вкладывать деньги для переноса своих задач на новые платформы.

Реализация функций API с помощью внешних библиотек - student2.ru 312________________ Глава 10. Краткий обзор современных операционных систем

Наши рекомендации