Разработка ядра Linux | страница 26



Встроенный ассемблер

Компилятор gcc С позволяет встраивать инструкции языка ассемблера в обычные функции языка С. Эта возможность, конечно, должна использоваться только в тех частях ядра, которые уникальны для определенной аппаратной платформы.

Для встраивания ассемблерного кода используется директива компилятора >asm().

Ядро Linux написано на смеси языков ассемблера и С. Язык ассемблера используется в низкоуровневых подсистемах и на участках кода, где нужна большая скорость выполнения. Большая часть коду ядра написана на языке программирования С.

Аннотация ветвлений

Компилятор gnu С имеет встроенные директивы, позволяющие оптимизировать различные ветви условных операторов, которые наиболее или наименее вероятны. Компилятор использует эти директивы для соответственной оптимизации кода. В ядре эти директивы заключаются в макросы >likely() и >unlikely(), которые легко использовать. Например, если используется оператор >if следующего вида:

>if (foo) {

> /* ... */

>}

то для того, чтобы отметить этот путь выполнения как маловероятный, необходимо указать:

>/* предполагается, что значение переменной foo равно нулю ...*/

>if (unlikely(foo)) {

> /* ... */

>}

И наоборот, чтобы отметить этот путь выполнения как наиболее вероятный

>/* предполагается, что значение переменной foo не равно нулю ...*/

>if (likely(foo)) {

> /* ... * /

>}

Эти директивы необходимо использовать только в случае, когда направление ветвления с большой вероятностью известно априори или когда необходима оптимизация какой-либо части кода за счет другой части. Важно помнить, что эти директивы дают увеличение производительности, когда направление ветвления предсказано правильно, однако приводят к потере производительности при неправильном предсказании. Наиболее часто директивы >unlikely() и >likely() используются для проверки ошибок.

Отсутствие защиты памяти

Когда прикладная программа предпринимает незаконную попытку обращения к памяти, ядро может перехватить эту ошибку и аварийно завершить соответствующий процесс. Если ядро предпринимает попытку некорректного обращения к памяти, то результаты могут быть менее контролируемы. Нарушение правил доступа к памяти в режиме ядра приводит к ошибке oops, которая является наиболее часто встречающейся ошибкой ядра. Не стоит говорить, что нельзя обращаться к запрещенным областям памяти, разыменовывать указатели со значением >NULL и так далее, однако в ядре ставки значительно выше!

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