Содержание


Разработка модулей ядра Linux

Часть 14. Компилятор GCC

Comments

Серия контента:

Этот контент является частью # из серии # статей: Разработка модулей ядра Linux

Следите за выходом новых статей этой серии.

Этот контент является частью серии:Разработка модулей ядра Linux

Следите за выходом новых статей этой серии.

В предыдущей статье был представлен обзор инструментария, который используется при создании модулей ядра. Но там не был представлен основной инструмент разработчика: компилятор! Так было сделано потому, что это ключевой инструмент, заслуживающий отдельного рассмотрения.

Компилятор GCC

Исходный код модулей ядра в Linux при всём богатстве языков, доступных в Linux для прикладного программирования, создаётся исключительно на языке C. Но после написания исходного кода модуля его необходимо скомпилировать. Даже для одного только языка C в Linux имеются и могут использоваться несколько различных компиляторов, перечисленных ниже:

  • основной компилятор Linux gcc, компилятор из GNU-проекта GCC;
  • компилятор cc из состава интегрированной среды разработки IDE Solaris Studio операционной системы Open Solaris (ещё недавно компании Sun Microsystems, а сегодня - компании Oracle);
  • активно развивающийся в рамках проекта LLVM компилятор Clang (кандидат для замены gcc в операционной системе FreeBSD из-за более подходящей лицензии);
  • PCC (Portable C Compiler) — новая реализация компилятора, развиваемого ещё с 70-х годов, получившая новую жизнь в операционных системах NetBSD и OpenBSD.

Все они и ещё некоторые из свободно развиваемых проектов могут с успехом использоваться в Linux (утверждается, что код, скомпилированный IDE Solaris Studio, в ряде случаев заметно превосходит по производительности код, скомпилированный gcc). Тем не менее все это многообразие доступно только в проектах для пользовательского адресного пространства, а в программировании ядра и, соответственно, модулей ядра на сегодняшний день применяется исключительно компилятор gcc. Причина этому — значительные синтаксические расширения gcc относительно стандартов языка C.

Примечание: Существуют экспериментальные проекты по сборке Linux компилятором, отличным от gcc. Есть сообщения о том, что компилятор Intel C обладает достаточной поддержкой расширений gcc, чтобы компилировать ядро Linux. Но при всех таких попытках пересборка может быть произведена только полностью, т.е. «с нуля»: сначала должно собраться ядро, и только потом можно выполнить сборку модулей. В любом случае, ядро и модули должны собираться одним компилятором.

Начало проекту GCC было положено Ричардом Столлманом, который реализовал первый вариант GCC в 1985 на нестандартном и непереносимом диалекте языка Паскаль. Позднее компилятор был переписан на языке Си Леонардом Тауэром и Ричардом Столлманом и выпущен в 1987 как компилятор для проекта GNU. Хронологически это один из старейших проектов GNU, непрерывно совершенствующийся на протяжении более 25 лет.

Одно из преимуществ (для разработчиков модулей ядра) компилятора gcc по сравнению с другими компиляторами - это расширенная и многоуровневая (древовидная) система справочных подсказок, включённых в саму утилиту gcc, начиная от простейшего указания версии:

$ gcc --version
gcc (GCC) 4.4.3 20100127 (Red Hat 4.4.3-4)
Copyright (C) 2010 Free Software Foundation, Inc.
...

Так, в зависимости от значений опционального параметра -help, может выводиться самая разная справочная информация, например, одна из полезных возможностей — показать опции компилятора, которые включены по умолчанию при указанном уровне оптимизации кода:

$ gcc -Q -O3 --help=optimizer

В листинге 1 перечислены ключи компилятора, контролирующие оптимизацию кода.

Листинг 1. Список опций компилятора
  -O<number>                  		 
  -Os                         		 
  -falign-functions           		[включено] 
  -falign-jumps               		[включено] 
...

Существует множество опций GCC, специфичных для каждой из поддерживаемых целевых платформ (архитектуры процессора), эти опции можно включить позже при компиляции модулей, например, в переменной EXTRA_CFLAGS, используемой Makefile. Проверить список опций, актуальных для текущей платформы, можно с помощью следующей команды:

$ gcc --target-help

В листинге 2 показаны примеры опций, специфических для платформы Intel x86.

Листинг 2. Машинно-зависимые опции для архитектуры Intel x86
...
  -m32          Генерировать 32-битный код i386
...
  -msoft-float  Не использовать аппаратную плавающую арифметику
  -msse         Включить поддержку внутренних функций MMX и SSE
  -msse2        Включить поддержку внутренних функций MMX, SSE и SSE2
...

В компилятор GCC добавлены значительные синтаксические расширения (например, ассемблерные инлайновые вставки или использование вложенных определений функций), которые не распознаются другими компиляторами языка C. В рамках этой статьи просто невозможно даже перечислить то множество возможностей, которое сложилось за 25 лет развития этого проекта, но существует исчерпывающе полное руководство по GCC, представленное в книге «GCC. Полное руководство» (см. раздел "Ресурсы"). Эту книгу рекомендуется постоянно держать на рабочем столе в качестве справочника.

Ассемблер в Linux

Следует сказать несколько слов и об ассемблере. Язык ассемблера практически никогда не требуется прикладному программисту. Но разработчику модулей в отдельных случаях он может помочь, часто даже не столько для написания конечного кода, сколько для понимания того, с чем приходится иметь дело (в коде ядра Linux достаточно много ассемблерных инлайновых вставок) в ходе экспериментов и отладки, а также при поиске ошибок. В сложных случаях иногда бывает полезно изучить ассемблерный код, генерируемый компилятором GCC в качестве промежуточного этапа компиляции и убедиться, что … компилятор вас неправильно понял. В конечном счёте, вопрос о том, нужно ли разработчику знание ассемблера должен пониматься так: разработчик модулей не обязан уметь писать код на языке ассемблера, но он должен понимать написанное на ассемблере и уметь различать подобный код. Можно было проигнорировать ассемблерные возможности gcc, но так как некоторые из представленных примеров используют такой код, то всё же следует сделать короткий экскурс в язык ассемблера.

Прежде всего, можно просмотреть ассемблерный код, сгенерированный GCC из исходного кода на языке C, если при запуске компилятора добавить к нему ключ –S.

$ gcc -S -o my_file.S my_file.c

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

В проекте GCC предполагается возможность использовать ассемблерный код для всех типов процессорных архитектур (x86, PPC, MIPS, AVR, ARM, ...), которые он поддерживает. При этом общий синтаксис записи в нотации AT&T (о котором будет подробно рассказано ниже) будет соблюдаться, но в деталях синтаксис будет отличаться от платформы к платформе, главным образом, за счёт различной конфигурации регистров процессора и их разного обозначения, а также различий в допустимых способах адресации для разных процессоров. Для генерации машинного кода компилятор gcc, в конечной фазе вызывает программу ассемблерного кодогенератора as, сконфигурированную под целевой процессор:

$ as --version
GNU assembler 2.17.50.0.6-6.el5 20061020
...
This assembler was configured for a target of `i386-redhat-linux'.

Присутствует заблуждение, что если в проекте GCC декларируется обширный перечень поддерживаемых процессорных архитектур, то из этого автоматически следует, что присутствующий в стандартной Linux-системе компилятор в состоянии выполнить компиляцию для всех этих платформ, например, в порядке кросс-компиляции. К сожалению, это не так, ведь потенциальное не означает реальное. Но всегда есть возможность найти и установить тот экземпляр (сборку) компилятора gcc, который осуществляет компиляцию для выбранной архитектуры. Другой способ получить такой компилятор – это, как и для большинства программных проектов GNU, собрать его самостоятельно из общедоступных исходных кодов проекта GCC.

Заключение

В данной статье был представлен краткий обзор компилятора gcc. Этот компилятор будет использоваться при работе со всеми последующими примерами, и без уверенного владения опциями этого компилятора трудно представить процесс разработки модулей ядра. В статье также было начато обсуждение использование ассемблера в процессе разработки модулей, и этот вопрос будет подробно изучен в следующей статье.


Ресурсы для скачивания


Похожие темы


Комментарии

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

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Linux, Open source
ArticleID=819120
ArticleTitle=Разработка модулей ядра Linux: Часть 14. Компилятор GCC
publish-date=05312012