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

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

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

Последний каталог со специализированными заголовочными файлами, который мы затронем, - это include/ibm. В нем располагается два файла с определениями, специфическими для компьютеров семейства IBM PC. Один из них, diskparam.h, необходим задаче гибкого диска. Исходный код этой задачи, хотя она и входит в стандартную поставку MINIX, не рассматривается в нашей книге, так как он по природе подобен коду задачи жесткого диска. В другом файле, partition.h, описываются таблицы разделов жестких дисков и соответствующие константы, специфичные для IBM-совместимых компьютеров. Эти файлы помещены в отдельный каталог для упрощения переноса ОС на другие аппаратные платформы. На другой платформе файл include/ibm/partition.h будет заменен другим файлом, скорее всего, это должен быть partition.h в соответствующим образом названном каталоге. Но в то же время внутренние структуры MINIX, определяемые файлом include/ minix/partition.h, должны остаться неизменными.

2.6.4. Структуры данных процессов и заголовочные файлы

Итак, теперь мы погрузимся глубже в MINIX и посмотрим, на что похож код в каталоге src/kernel. В двух предыдущих разделах дискуссия была построена вокруг выжимки из типичного основного заголовочного файла. Сейчас мы сперва познакомимся с настоящим системным заголовочным файлом, kernel.h. Он начинается с объявления трех макросов. Первый из них - POSIX SOURCE, макрос проверки поддерживаемых функций, определяемый самим стандартом POSIX. Все подобные макросы начинаются с символа подчеркивания, . Этот макрос включается для того, чтобы были видимы все символы, как требуемые стандартом, так и разрешенные, но не обязательные, а неофициальные расширения были бы скрыты. Следующие два макроопределения уже были упомянуты, это макрос MINIX, переопределяющий эффект макроса POSIX SOURCE для расширений MINIX, и макрос SYSTEM, наличие которого проверяется там, где при компиляции необходимо учитывать разницу между системным и пользовательским кодом (например, может меняться знак кода возврата). Затем в kernel.h включаются другие заголовочные файлы из include/ и подкаталога include/sys/ и include/minix/, в том числе те, что перечислены в листинге 2.12. Все эти файлы уже были нами рассмотрены в двух предыдущих разделах. Затем присоединяются еще четыре заголовочных файла из src/kernel/.

Здесь для новичков в программировании на С нужно упомянуть о том, что обозначают различные виды скобок в директиве #include. У каждого компилятора С имеется каталог, в котором по умолчанию ищутся включаемые файлы. Обычно это /usr/include, как принято в MINIX. Когда имя включаемого файла записано в угловых скобках (<...>), компилятор ищет его в каталоге по умолчанию или в одном из подкаталогов, если таковой указан. Если же имя файла за-



писано в кавычках, компилятор сначала просматривает текущий каталог (или подкаталог, если он указан), и если нужный файл не найден, он ищется в каталоге по умолчанию.

Файл kernel, h позволяет легко включить большое количество всех необходимых определений при помощи одной команды, имеющейся во всех файлах с кодами ядра:

#include kernel h

Иногда имеет значение то, в каком порядке включаются различные заголовочные файлы. А именно использование kernel, h позволяет раз и навсегда гарантировать соблюдение требуемой последовательности. Это поднимает концепцию сделал и забыл , реализуемую заголовочными файлами, на более высокий уровень. В каталогах с кодами файловой системы и менеджера памяти имеются аналогичные главные заголовочные файлы.

Теперь давайте перейдем к четырем локальным файлам, включаемым в kernel, h. Точно так же, как в include/minix/ имелись файлы const.h и type.h, в каталоге с исходными кодами ядра, src/kernel/, присутствуют свои const.h и type.h. Те файлы, что размещены в include/minix/, помещены там потому, что они необходимы для компиляции различных частей системы, включая программы, работающие под ее управлением. Файлы в src/kernel/ содержат определения, используемые только для компиляции ядра. Аналогичные файлы есть и в каталогах с исходными кодами файловой системы и менеджера памяти, эти файлы определяют типы и константы, принципиальные только для компиляции данных частей системы.

Следующие два файла, включаемые в kerneLh, proto.h и glo.h, не имеют аналогов в общем каталоге include/, но, как будет видно позже, в файловой системе и менеджере памяти аналогичные файлы имеют место.

В const.h определен ряд мащинно-зависимых значений, то есть констант, специфических для процессоров Intel. При компиляции для других процессоров эти значения, скорее всего, будут другими. Они помещены между директивами условной компиляции:

#1f (CHIP == INTEL) И

#endi f

Когда система компилируется для процессора Intel, в файле config.h определяются макросы CHIP и INTEL, в результате чего мащинно-зависимый код будет сгенерирован. При переносе MINIX на систему, в основе которой будет процессор Motorola 68000, в этот код будет добавлена еще одна секция, помещенная между следующими директивами: #if (CHIP -= М6800)

#endi f

A в файле include/minix/config.h макрос CHIP будет переопределен так: #define CHIP М6800



Описанная методика позволяет MINIX использовать константы и код, зависящие от аппаратной платформы. Но это плохо сказывается на читаемости кода, поэтому подобными конструкциями злоупотреблять не следует.

Особого внимания заслуживают еще несколько определений из const.h. Часть из них машинно-зависимые, например основные векторы прерываний и значения полей, требуемые для сброса контроллера прерываний после возбуждения каждого прерывания. У каждой задачи в ядре имеется собственный стек, но при обработке прерываний используется особый стек, размер которого определяется константой K STACK BYTES. Эта константа находится в машинно-зависимой секции, так как для другой архитектуры может потребоваться стек другого размера, большего или меньшего.

Прочие определения платформно-независимы, но встречаются во многих местах кода ядра. Так, у планировщика процессов MINIX имеются три очереди NQ с разными приоритетами, которые соответственно называются TASK Q (высший приоритет), SERVER Q (средний уровень приоритета) и USER Q (наименьший приоритет). Эти имена введены для улучшения читаемости кода, а при компиляции подменяются числовыми значениями. Наконец, последней строкой const.h определяется макрос printf, который будет разворачиваться как printk. Это позволяет ядру выводить на консоль сообщения при помощи имеющихся в ядре процедур, что необходимо для обхода обычного механизма вывода сообщений, который требует передачи сообщения сначала файловой системе, а затем из файловой системы - задаче принтера. Дело в том, что при сбое системы такой механизм может не работать. Пример вызова printf смотрите в процедуре с именем panic, которая, как несложно понять по ее имени, вызывается в случае фатальных сбоев.

В файле type.h определены несколько прототипов и структур, нужных для любой реализации MINIX. Структура tasktab описывает отдельную запись массива tasktab, а поля структуры memory содержат два значения, однозначно определяющих область памяти. Здесь нужно упомянуть некоторые концепции, имеющие отношение к организации памяти. Минимальный блок памяти называется кликом (click). В MINIX для процессоров Intel эта величина равна 256 байт. Память измеряется в phys clicks, удобных ядру для обращения к любой ячейке памяти по всей системе, или в vir cHcks, если к памяти обращается какой-либо другой процесс помимо ядра. Ссылка на ячейку памяти, хранящаяся в vir clicks, указывает ячейку относительно базового сегмента памяти, присвоенного конкретному процессу. Это неудобство окупается тем, что каждый процесс имеет собственную область памяти, на которую он вправе ссылаться через vir clicks. Последнее позволяет при обращении к памяти проверять, что процесс не выходит за границы области памяти, выделенной специально для него. Такая защита памяти - одна из основных особенностей защищенного режима современных процессоров Intel. Отсутствие защищенного режима в ранних процессорах, таких как 8086 и 8088, вызывало немало головных болей у разработчиков первых версий MINIX.

В type.h находится описание нескольких типов, также зависящих от аппаратной реализации. Это типы port t, segm t и reg t. В версии для процессоров Intel



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.
Копирование материалов разрешено исключительно при условии цититирования.