Разработка ядра Linux - Роберт Лав
Шрифт:
Интервал:
Закладка:
Третья строка позволяет указать значение этого параметра по умолчанию, который соответствует в данном случае запрещению компиляции.
Директива help указывает на то, что остальная часть текста будет интерпретироваться как описание данного модуля. Различные конфигурационные утилиты могут при необходимости отображать этот текст. Так как этот текст предназначен для пользователей и разработчиков, которые будут компилировать ядро, то он должен быть коротким и ясным. Обычные пользователя, скорее всего, не будут компилировать ядро, а сели будут, то тогда они должны понимать, что в этом описании сказано.
Существуют также и другие директивы файла конфигурации. Директива depends указывает на конфигурационные параметры, которые должны быть установлены перед тем, как может быть установлен текущий параметр. Если зависимости не будут удовлетворены, то текущий параметр будет запрещен. Например, можно указать следующую директиву.
depends on FISH_TANK
При этом текущий модуль не будет разрешен, пока не будет разрешен модуль, соответствующий конфигурационному параметру CONFIG_FISH_TANK.
Директива select аналогична директиве depends, за исключением того, что она принудительно включает указанный конфигурационный параметр, если включается текущая конфигурационная опция. Ее не нужно использовать так же часто, как директиву depends, потому что она включает другие конфигурационные опции. Использовать ее так же просто.
select BAIT
В этом случае конфигурационный параметр CONFIG_BAIT автоматически активизируется при включении конфигурационного параметра CONFIG_FISHING_POLE.
Как для директивы select, так и для директивы depends можно указывать несколько параметров с помощью оператора &&. В директиве depends с помощью восклицательного знака перед параметром можно указать требование, что некоторый конфигурационный параметр не должен быть установлен. Например, следующая запись указывает, что для компиляции текущего драйвера необходимо, чтобы был установлен конфигурационный параметр CONFIG_DUMB_DRIVERS и не был установлен параметр CONFIG_NO_FISHING_ALLOWED.
depends on DUMB_DRIVERS && !NO_FISHING_ALLOWED
После директив tristate и bool можно указать директиву if, что позволяет сделать соответствующий параметр зависимым от другого конфигурационного параметра. Если условие не выполняется, то конфигурационный параметр не только запрещается, но и не будет отображаться утилитами конфигурации. Например, следующая строка указывает, что функция "Deep Sea Mode" будет доступна, только если разрешен конфигурационный параметр CONFIG_OCEAN.
bool "Deep Sea Mode" if OCEAN
Директива if также может быть указана после директивы default, что означает, что значение по умолчанию будет установлено, только если выполняется условие, указанное в директиве if.
Система конфигурации экспортирует несколько метапараметров, чтобы упростить процесс конфигурации. Параметр CONFIG_EMBEDDED устанавливается только тогда, когда пользователь указывает, что он хочет видеть вес параметры, отвечающие за запрещение некоторых ключевых возможностей ядра (обычно с целью сохранения памяти на встраиваемых системах). Параметр CONFIG_BROKEN_ON_SMP используется, чтобы указать, что драйвер не рассчитан на системы с симметричной многопроцессорностью. Обычно этот параметр не устанавливается, при этом от пользователя требуется, чтобы он сам убедился в возможности компиляции драйвера для SMP. Новые драйверы этот флаг использовать не должны.
Параметр CONFIG_EXPERIMENTAL используется для указания экспериментальных или не очень хорошо оттестированных возможностей. По умолчанию этот параметр отключен, что требует от пользователя лично убедиться в степени риска при разрешении компиляции того или иного драйвера.
Параметры модулей
Ядро Linux предоставляет возможность драйверам определять параметры, которые пользователь будет указывать при загрузке ядра или модуля. Эти параметры будут доступны коду модуля в качестве глобальных переменных. Указанные параметры модулей также будут отображаться в файловой системе sysfs (см. главу 17, "Объекты kobject и файловая система sysfs"). Определять параметры модуля и управлять ими просто.
Параметр модуля определяется с помощью макроса module_param() следующим образом.
module_param(name, type, perm);
где аргумент name — это имя неременной, которая появляется в модуле, и имя параметра, который может указать пользователь. Аргумент type — это тип данных параметра. Значения типа могут быть следующими: byte, short, ushort, int, uint, long, ulong, charp, bool или invbool. Эти значения соответствуют следующим типам данных: байт; короткое целое число; короткое целое число без знака; целое число; целое число без знака; длинное целое; длинное целое число без знака; указатель на строку символов; булев тип; булев тип, значение которого инвертируется по сравнению с тем, которое указывает пользователь. Данные типа byte хранятся в переменной типа char, а данные булевых типов — в переменных типа int. Остальные- типы соответствуют аналогичным типам языка С. Наконец, аргумент perm указывает права доступа к соответствующему файлу в файловой системе sysfs. Права доступа можно указать как в обычном восьмеричном формате, например 0644 (владелец имеет права на чтение и запись, группа имеет права на чтение и запись, остальные пользователи имеют право только на чтение), так и в виде определений препроцессора, объединенных с помощью оператора "|", например S_IRUGO | S_IWUSR (все могут считывать данные, а владелец также и записывать). Нулевое значение этого параметра приводит к тому, что соответствующий файл в файловой системе sysfs не появляется.
Этот макрос не определяет переменную. Перед тем как использовать макрос, соответствующую переменную нужно определить. В связи с этим типичный пример использования может быть следующим.
/* параметр модуля, который управляет переменной bait */
static int allow live bait = 1; /* по умолчанию включено */
module_param(allow_live_bait, bool, 0644); /* булев тип */
Это определение должно быть в глобальной области видимости, т.е. неременная allow_live_bait должна быть глобальной.
Существует возможность дать внешнему параметру модуля имя, отличное от имени переменной. Это можно сделать с помощью макроса module_param_named().
module_param_named(name, variable, type, perm);
где name — это имя внешнего параметра модуля, a variable — имя внутренней глобальной переменной модуля, как показано ниже.
static unsigned int max_test = DEFAULT_МАХ_LINE_TEST;
module_param_named(maximum_line_test, max_test, int, 0);
Для того чтобы определить параметр модуля, значением которого является строка символов, необходимо использовать тип charp. Ядро копирует переданную пользователем строку символов в память и присваивает переменной указатель на эту строку, как в следующем примере.
static char *name;
module_param(name, charp, 0);
При необходимости ядро может скопировать строку в заранее определенный массив символов, который указывает разработчик. Это делается с помощью макроса module_param_string().
module_param_string(name, string, len, perm);
где name — это имя внешнего параметра, string — имя внутренней переменной, которая содержит указатель на область памяти массива, len — размер буфера string (или некоторое меньшее число, чем размер буфера, что, однако, обычно не имеет смысла), perm — права доступа к файлу на файловой системе sysfs (нулевое значение запрещает доступ к параметру через sysfs). Пример показан ниже.
static char species[BUF_LEN];
module_param_string(specifies, species, BUF_LEN, 0);
В качестве параметров модуля также можно передавать список значений, которые разделены запятой и в коде модуля будут записаны в массив данных. Эти параметры модуля можно обработать с помощью макроса module_param_array() следующим образом.
module_param_array(name, type, nump, perm);
В данном случае аргумент name — это имя внешнего параметра и внутренней переменной, type — это тип данных одного значения, a perm — это права доступа к файлу на файловой системе sysfs. Новый аргумент nump — это указатель на целочисленное значение, где ядро сохраняет количество элементов, записанных в массив. Обратите внимание, что массив, который передается в качестве параметра name, должен быть выделен статически. Ядро определяет размер массива на этапе компиляции и гарантирует, что он не будет переполнен. Как использовать данный макрос, показано в следующем примере.
static int fish[MAX_FISH];
static int nr_fish;
module_param_array(fish, int, &nr_fish, 0444);