Ядро имеет некоторые отличия в сравнении с обычными пользовательскими приложениями, эти отличия хотя и не обязательно приводят к серьезным усложнениям при программировании, но все же создают специфические проблемы при разработке ядра.
Эти отличия делают ядро зверьком другого рода . Некоторые из старых правил при этом остаются в силе, а некоторые правила являются полностью новыми. Хотя часть различий очевидна (все знают, что ядро может делать все, что пожелает), другие различия не так очевидны. Наиболее важные отличия описаны ниже.
• Ядро не имеет доступа к библиотеке функций языка С.
• Ядро программируется с использованием компилятора GNU С.
• В ядре нет такой защиты памяти, как в режиме пользователя.
• В ядре нельзя легко использовать вычисления с плавающей точкой.
• Ядро использует стек небольшого фиксированного размера.
• Поскольку в ядре используются асинхронные прерывания, ядро является преемптивным и в ядре имеется поддержка SMP, то в ядре необходимо учитывать наличие параллелизма и использовать синхронизацию.
• Переносимость очень важна.
Давайте рассмотрим более детально все эти проблемы, так как все разработчики ядра должны постоянно помнить о них.
Отсутствие библиотеки libc
В отличие от обычных пользовательских приложений, ядро не компонуется со стандартной библиотекой функций языка С (и ни с какой другой библиотекой такого же типа). Для этого есть несколько причин, включая некоторые ситуации с дилеммой о курице и яйце, однако первопричина — скорость выполнения и объем кода. Полная библиотека функций языка С, и даже только самая необходимая ее часть, очень большая и неэффективная для ядра.
При этом не нужно расстраиваться, так как многие из функций библиотеки языка С реализованы в ядре. Например, обычные функции работы со строками описаны в файле lib/string.с
. Необходимо лишь подключить заголовочный файл и пользоваться этими функциями.
Заголовочные файлы
Заметим, что упомянутые заголовочные файлы и заголовочные файлы, которые будут упоминаться далее в этой книге, принадлежат дереву исходного кода ядра. В файлах исходного кода ядра нельзя подключать заголовочные файлы извне этого дерева каталогов, так же как и нельзя использовать внешние библиотеки,
Отсутствует наиболее известная функция printf()
. Ядро не имеет доступа к функции printf()
, однако ему доступна функция printk()
. Функция printk()
копирует форматированную строку в буфер системных сообщений ядра (kernel log buffer), который обычно читается с помощью программы syslog
. Использование этой функции аналогично использованию printf()
:
printk("Hello world! Строка: %s и целое число: %d\n",
a_string, an_integer);
Одно важное отличие между printf()
и printk()
состоит в том, что в функции printk()
можно использовать флаг уровня вывода. Этот флаг используется программой syslog
для того, чтобы определить, нужно ли показывать сообщение ядра. Вот пример использования уровня вывода:
printk(KERN_ERR "Это была ошибка !\n");
Функция printk()
будет использоваться на протяжении всей книги. В следующих главах приведено больше информации о функции printk()
.
Как и все "уважающие себя" ядра Unix, ядро Linux написано на языке С. Может быть, это покажется неожиданным, но ядро Linux написано не на чистом языке С в стандарте ANSI С. Наоборот, где это возможно, разработчики ядра используют различные расширения языка, которые доступны с помощью средств компиляции gcc (GNU Compiler Collection — коллекция компиляторов GNU, в которой содержится компилятор С, используемый для компиляции ядра).
Разработчики ядра используют как расширения языка С ISO C99 [7] Стандарт ISO C99 — это последняя основная версия редакции стандарта ISO С. Редакция C99 содержит многочисленные улучшения предыдущей основной редакции этого стандарта. Стандарт ISO C99 вводит поименную инициализацию полей структур и тип complex .
так и расширения GNU С. Эти изменения связывают ядро Linux с компилятором gcc, хотя современные компиляторы, такие как Intel С, имеют достаточную поддержку возможностей компилятора gcc для того, чтобы ими тоже можно было компилировать ядро Linux. В ядре не используются какие-либо особенные расширения стандарта C99, и кроме того, поскольку стандарт C99 является официальной редакцией языка С, эти расширения редко приводят к возникновению ошибок в других частях кода. Более интересные и, возможно, менее знакомые отклонения от стандарта языка ANSI С связаны с расширениями GNU С. Давайте рассмотрим некоторые наиболее интересные расширения, которые могут встретиться в программном коде ядра.
Читать дальше