Главная страница  Межпроцессное взаимодействие (состязание) 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 [ 39 ] 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187

Таким образом, когда заголовочный файл включается при компиляции table.c, ключевое слово extern перед объявлениями переменных не ставится (так как в файле table.c макрос EXTERN определен как пустая строка), поэтому все глобальные переменные размещаются в одном месте, в объектном файле table.o.

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

Макрос PRIVATE синонимичен ключевому слову static. Этот макрос всегда применяется для объявления переменных и функций, на которые не будут ссылаться другие компоненты системы, чтобы имена этих объектов не были видимы за пределами того файла, где они объявлены. Как правило, переменные и процедуры необходимо по возможности размещать в локальной области видимости. Макрос PUBLIC определен как пустая строка. Так, например, декларация:

PUBLIC void free 2one(Dev t dev. 2one t numb)

преобразуется препроцессором в следующий код:

void free 2one(0ev t dev. 2one t numb)

который, в соответствии с синтаксическими правилами языка С, означает, что функция с именем free zone экспортируется и может быть использована в других файлах. Использовать макросы PRIVATE и PUBLIC необязательно, это только попытка исправить проблемы, вносимые соглащениями С (где по умолчанию имена размещаются в глобальной области видимости, а должно быть наоборот).

В оставшейся части файла const.h определяются константы, повсеместно используемые в системе. Так, например, везде и всюду в коде фигурирует величина базового блока памяти, зависящая от архитектуры системы. Кроме того, в этом файле определяются удобные макросы МАХ и MIN, позволяющие для вычисления большего из двух значений применять следующую запись:

2 = МАХ(х. у):

Еще один файл, косвенно включаемый при каждой компиляции в главных заголовочных файлах, - это type.h. В нем содержится ряд описаний ключевых типов и связанных с ними числовых констант. Самый важный тип здесь - message (сообщение). Его можно было бы задать как массив определенного количества байтов, но ради хорошего стиля программирования он описан как структура, содержащая объединение различных возможных типов сообщений. Всего имеется шесть форматов сообщений, с именами от mess l до mess 6. В самой структуре message есть поле m source с информацией об отправителе сообщения, поле m type, говорящее о том, каков формат сообщения (например, для задачи таймера это может быть GET TIME), и поля с данными сообщения. Структуры шести типов сообщений показаны на рис. 2.15. На этом рисунке первая и вторая структура кажутся одинаковыми, равно как и вторая и четвертая, что действительно



так для 32-разрядных реализаций MINIX на платформе Intel. Но для других машин, где типы int, long и указатели могут иметь другой размер, это не факт. Поэтому для упрощения компиляции и определено шесть различных структур.

m source

m type

m1 i1

ml 12

m1 i3

m1 p1

m1 p2

m1 p3

m source

m type

m2 И

m2 12

m2 is

m2 11

ml 12

m2 p1

m source

m type

mS И

mS 12

mS cal

m source

m type

m4 11

m4 12

m4 13

m4 14

m4 15

m source

m type m5 c2m53l

m5 il

m5 i2

m5 l1

m5 i2

m5 13

m source

m type

m6 il

m6 i2

m6 iS

m6 il

m6 fl

Рис. 2.15. Структуры шести типов сообщений, используемых в IVIiNIX. Размеры элементов могут меняться, в зависимости от архитектуры целевой машины. Диаграмма соответствует компьютеру с 32-разрядными указателями, например Pentium (Pro)

Когда необходимо передать сообщение, содержащее, к примеру, три целочисленных значения и три указателя, задействуется первая структура. Подобным же образом используются и другие форматы. Как же можно присвоить нужное значение первому целочисленному полю в первой структуре? Предположим, что сообщение имеет имя х. Тогда объединение (union), содержащее параметры сообщения, будет иметь имя x.m u. Чтобы обратиться к первой структуре этого объединения, подставляется имя x.m u.m ml. Наконец, чтобы обратиться к первому целочисленному полю в этой структуре, следует применять запись: x.m u.m ml.mlil. Она довольно многословна, поэтому после описания самого типа message описываются несколько макроопределений, слегка укорачивающих запись. Так, x.m u.m ml.mlil становится заменяемой x.mljl. Укороченные имена имеют следующий формат: они начинаются с буквы т , затем следует номер структуры, знак подчеркивания, один или два символа, обозначающие тип значения (целое число, указатель, длинное целое, символ, массив символов, функция), после чего записывается число, позволяющее локализовать нужное поле в структуре.

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



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

Есть в каталоге include/minix еще один файл, сквозной по всей системе благодаря тому, что включен в основные заголовочные файлы. Это файл syslib.h, содержащий прототипы библиотечных функций языка С, которые в системе используются для доступа к прочим службам ОС. Библиотеки С не обсуждаются в книге, но больщая часть из них стандартна и поставляется с любым компилятором. Тем не менее сами функции, прототипы которых содержатся в файле syslib.h, специфичны для операционной системы, и при переносе MINIX на новую платформу с другим компилятором должны быть переписаны. К счастью, последнее несложно, так как назначение этих функций в том, чтобы извлечь нужные параметры, заполнить ими структуру сообщения, после чего отправить сообщение и извлечь ожидаемые значения из ответа. Как правило, в каждом таком случае требуется не больше дюжины строк кода.

В MINIX, когда процессу нужно сделать системный вызов, он посылает сообщение файловой системе (или, для краткости, FS) или менеджеру памяти (ММ). Каждое такое сообщение должно содержать номер требуемого системного вызова. Соответствующие номера перечислены в файле callnr.h.

В файле com.h находятся описания, в основном актуальные при взаимодействии менеджера памяти или файловой системы с задачами ввода/вывода. Кроме того, здесь же указаны номера, соответствующие разным задачам. Задачам присвоены отрицательные номера, чтобы можно было отличать их от процессов. В этом же заголовочном файле описаны типы сообщений (коды функций), которые могут быть посланы каждой из задач. Например, задача таймера воспринимает коды SET ALARM (установка таймера), CLOCK TICK (возникновение прерывания таймера), GET TIME (запрос времени) и SET TIME (установка времени). Ответ на сообщение GET TIME имеет код REAL TIME.

Наконец, в каталоге include/minix содержатся несколько более специфических заголовочных файлов. Среди них - boot.h, который необходим ядру и файловой системе для детектирования устройств и доступа к данным, переданным программе boot. Еще один файл - key тар. h, задает структуры, необходимые для реализации различных национальных раскладок клавиатур. Этот файл нужен программам, генерирующим и загружающим таблицы символов. Другие файлы каталога, такие как partition.h, представляют интерес исключительно для ядра и не требуются файловой системе или менеджеру памяти. Кроме того, если в вашей реализации системы имеется поддержка дополнительных устройств ввода/вывода, то в этом каталоге будут находиться еще несколько подобных файлов, поддерживающих взаимодействие с 1/О-устройствами. Структура каталога include/minix требует дополнительного пояснения. Дело в том, что в идеале пользовательские профаммы должны взаимодействовать с устройствами ввода/вывода исключительно через операционную систему, тогда подобные файлы должны были быть размещены в src/kernel. Тем не менее реалии работы с системой требуют, чтобы



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 [ 39 ] 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187

© 2000 - 2018 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования.