Ядро Linux в комментариях

       

Checksetup


Функция checksetup обеспечивает обработку большинства параметров ядра. Различают три категории параметров: использующие нормальные параметры ядра, разбираемые в части после знака =; разбираемые в части после знака = самостоятельно; разбираемые в части до и после знака =. На первую категорию ссылаются как на «обработанные» параметры, тогда как на вторую — как на «сырые». К последней категории относится только параметр IDE, имеющий отношение к драйверу IDE; этот случай проверяется первым в строке .

Далее checksetup сканирует массив raw_params (строка ) на предмет того, должен ли данный параметр оставаться необработанным. Элементы raw_params имеют тип struct kernel_param (строка ), ассоциирующий префикс параметра с функцией, которая вызывается, если такой параметр будет найден. Если атрибут str в каком-то элементе массива предваряется содержимым line, производится вызов соответствующей функции с передачей ей оставшейся части line и checksetup вернет ненулевое значение, которое говорит о том, что данный параметр обработан. Массив raw_params завершается двумя элементами NULL, поэтому цикл завершается также при встрече атрибута str, равного NULL. В таком случае цикл очевидно переходит в конец массива raw_params, не отыскав ни одного совпадения. Естественно, проверка атрибута setup_func функционирует в равной степени хорошо. Рассмотренный цикл иллюстрирует одно утверждение: в отличие от большей части ядра, инициализация не должна выполняться настолько быстро, насколько это возможно. Если даже ядро потратит на инициализацию на несколько микросекунд больше, чем планировалось, нет никаких оснований искать потери — пока еще никаких пользовательских приложений не запускалось, посему и терять-то нечего. В результате код выглядит необычно непроизводительным и требующим очевидной оптимизации. Например, длины строк в массиве raw_params можно было бы сохранить в том же массиве, а не вычислять их каждый раз (см. строку ). Для достижения еще больших результатов можно было отсортировать элементы массива raw_params в алфавитном порядке и предоставить возможность checksetup выполнять более быстрый двоичный поиск.


Нет ни малейших препятствий внести подобного рода усовершенствования в raw_params, однако, вряд ли игра будет стоить свеч, поскольку двоичный поиск дает существенную экономию только на больших массивах (точное значение признака «большой» зависит от конкретных обстоятельств). Коллега raw_params, массив cooked_params (строка ), определенно обладает большими возможностями для оптимизации, однако с ним связана одна проблема: сортировка по алфавиту может оказаться затруднительной, поскольку потребует разделения некоторых блоков #ifdef (см. строки с по ). Кроме того, из-за того, что алгоритм должен выполнять поиск по префиксам, он может оказаться чувствительным к порядку следования элементов. Все же упомянутые задачи не являются главенствующими и потенциальное возрастание производительности не стоит затраченного на это труда (в конце концов, дерево префиксов можно построить и статически). В данном случае предпочтение было отдано простоте.

Тем не менее, в аналогичном массиве root_dev_names (см. строку ), который отображает префиксы имен аппаратных устройств на их идентификаторы, разработчики несколько повысили производительность, поместив более часто используемые элементы (диски IDE и SCSI) перед менее часто используемыми (IDE-устройства чтения CD-ROM с интерфейсом подключения к порту принтера). Ничего подобного в случае raw_params и cooked_params не замечено.

Еще одно замечание. Уже сейчас можно предположить, почему параметры ro, rw и debug проверяются в parse_options, а не здесь — в parse_options выполняется полное сравнение, в то время как в checksetup проверяются только префиксы. В частности, параметр ro оказывается префиксом root= (строка ), а все должно работать корректно даже в случае присутствия в строке параметров и ro, и root=. Конечно, аргумент выглядит довольно-таки слабо. Посмотрите на параметр noinitrd (строка ). Он анализируется в cooked_params и, стало быть, подпадает под сравнение лишь префиксов; связанная с ним функция (no_initrd, строка ) игнорирует любые передаваемые ей параметры, т.е. ro, rw и debug, которые могут попасть в cooked_params.

Этот цикл выполняет те же самые действия над массивом cooked_params, что и предыдущий цикл делал по отношению к raw_params. Единственное отличие между упомянутыми циклами (помимо массивов, конечно) состоит в том, что данный цикл имеет дело с частью line после знака =, вызывая get_options (строка ) перед обращением к функции установки. Функция get_options заполняет массив ints максимум десятью отрицательными числами. ints[0] хранит количество используемых элементов массива, т.е. сколько раз int get_options сохранялось в ints. Заполненный массив затем передается в функцию установки, которая соответствующим образом его интерпретирует.

Возвращается 0, означающий, что параметр ядра в line не распознался.


Содержание раздела