netlib.narod.ru< Назад | Оглавление | Далее >

Использование свойств, специфических для gcc

Ядро Linux создавалось таким образом, чтобы легко компилироваться компилятором GNU C, т.е. gcc.

Ядро может быть откомпилировано далеко не в каждом компиляторе С, поскольку нередко в коде задействуются возможности, специфические для gcc. Большинство таких возможностей подробно описываются по ходу изложения материала. В части кода используются языковые расширения gcc, например, применение ключевого слова inline в С (не С++) для определения inline-функции, т.е. функции, чей код будет подставляться при каждом ее вызове, тем самым экономя затраты на обычный вызов функции.

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

Например, давайте обсудим частоту использования goto в ядре — во имя скорости ядро частенько прибегает к этому обычно нежелательному оператору. В почти 40000 строк кода goto встречается более 500 раз, т.е. один goto на приблизительно 80 строк кода. Если не принимать во внимание ассемблерный код, получается один goto на около 72 строк. Справедливости ради следует отметить, что такая частота использования goto связана, прежде всего, со спецификой выбранного кода — в основной части ядра, рассматриваемой в книге, наиболее важным требованием является скорость. Частота использования goto для ядра в целом составляет один goto на 260 строк, что представляет собой довольно большое значение.

Практика написания кода под конкретный компилятор достаточно резко противоречит идеологии разработки не только большинства прикладных приложений, но также и ядра. Разработчики прибегают к языку С по причине сохранения переносимости результирующего кода, даже если это код ОС. Преимущества здесь очевидны: взять хотя бы возможность перейти на другой, более мощный компилятор, как только он становится доступным.

Тесная привязка ядра к особенностям gcc существенно усложняет перенос кода ядра в другие компиляторы. Недавно Линус изложил свою позицию по этому поводу в конференции, посвященной ядру: «Помните: компилятор — это ИНСТРУМЕНТ». Такое утверждение прекрасно характеризует философию, лежащую в основе привязки к специфике gcc, — компилятор необходим только для завершения работы. Если критерии работы не могут быть реализованы в рамках существующих стандартов, следует отказываться от стандартов, но не от критериев работы.

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

Однако в данном случае Линус прав. Ядро Linux — специальный случай, при котором скорость выполнения результирующего кода играет гораздо большую роль, нежели переносимость исходного кода в другие компиляторы. Если бы цель заключалась в создании переносимого, а не быстродействующего, ядра, либо ядра, которое каждый смог бы компилировать в любом компиляторе, решение оказалось бы другим. Но не эти цели заложены в Linux. На практике gcc генерирует код, который выполняется практически на каждом процессоре, поэтому базирование на gcc — не столь уж большой барьер для переносимости.

Дополнительное обсуждение целей проектирования ядра можно найти в главе 3.


netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz