Примеры программирования для разных интерфейсов 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 { продолжение


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_________________ 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. При их разработке создатели, как правило, стараются реализовать функционально пол­ный набор основных функций, используя которые можно решать разные задачи, правда, порой, различными способами. Один набор системных функций хорош для


310______________________________ Глава 9. Архитектура операционных систем

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

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

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

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

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

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

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

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

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

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

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

 

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

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


Глава 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, она была одной из первых полноцен­ных и надежных мультипрограммных и мультизадачных операционных систем для персональных компьютеров, в которой поддерживалось несколько опера­ционных сред.

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


312________________ Глава 10. Краткий обзор современных операционных систем








Дата добавления: 2016-09-20; просмотров: 617;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.018 сек.