Разработка ядра Linux | страница 26
Компилятор gcc С позволяет встраивать инструкции языка ассемблера в обычные функции языка С. Эта возможность, конечно, должна использоваться только в тех частях ядра, которые уникальны для определенной аппаратной платформы.
Для встраивания ассемблерного кода используется директива компилятора >asm()
.
Ядро Linux написано на смеси языков ассемблера и С. Язык ассемблера используется в низкоуровневых подсистемах и на участках кода, где нужна большая скорость выполнения. Большая часть коду ядра написана на языке программирования С.
Компилятор gnu С имеет встроенные директивы, позволяющие оптимизировать различные ветви условных операторов, которые наиболее или наименее вероятны. Компилятор использует эти директивы для соответственной оптимизации кода. В ядре эти директивы заключаются в макросы >likely()
и >unlikely()
, которые легко использовать. Например, если используется оператор >if
следующего вида:
>if (foo) {
> /* ... */
>}
то для того, чтобы отметить этот путь выполнения как маловероятный, необходимо указать:
>/* предполагается, что значение переменной foo равно нулю ...*/
>if (unlikely(foo)) {
> /* ... */
>}
И наоборот, чтобы отметить этот путь выполнения как наиболее вероятный
>/* предполагается, что значение переменной foo не равно нулю ...*/
>if (likely(foo)) {
> /* ... * /
>}
Эти директивы необходимо использовать только в случае, когда направление ветвления с большой вероятностью известно априори или когда необходима оптимизация какой-либо части кода за счет другой части. Важно помнить, что эти директивы дают увеличение производительности, когда направление ветвления предсказано правильно, однако приводят к потере производительности при неправильном предсказании. Наиболее часто директивы >unlikely()
и >likely()
используются для проверки ошибок.
Отсутствие защиты памяти
Когда прикладная программа предпринимает незаконную попытку обращения к памяти, ядро может перехватить эту ошибку и аварийно завершить соответствующий процесс. Если ядро предпринимает попытку некорректного обращения к памяти, то результаты могут быть менее контролируемы. Нарушение правил доступа к памяти в режиме ядра приводит к ошибке oops, которая является наиболее часто встречающейся ошибкой ядра. Не стоит говорить, что нельзя обращаться к запрещенным областям памяти, разыменовывать указатели со значением >NULL
и так далее, однако в ядре ставки значительно выше!
Кроме того, память ядра не использует замещение страниц. Поэтому каждый байт памяти, который использован в ядре, — это еще один байт доступной физической памяти. Это необходимо помнить всякий раз, когда добавляются новые