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

Struct ctl_table


Это центральная структура данных, используемая в коде, который описан в этой главе. Объекты struct ctl_table обычно объединяются в массивы и каждый такой массив соответствует входам в отдельном каталоге, находящемся где-то под каталогом /proc/sys. (По мнению автора, этот тип данных лучше было бы назвать struct ctl_table_entry.) Объект root_table (строка ) и массивы, которые следуют за ним, создают дерево массивов, в которых указатели child объекта struct ctl_table используются для соединения узлов дерева (указатели child рассматриваются в приведенном ниже списке). Отметим, что все эти массивы являются массивами объекта ctl_table, который просто служит объявлением typedef для объекта struct ctl_table; это установлено в строке .

Связь в виде дерева массивов показана на рис. 11.1.


Рис. 11.1. Часть дерева объектов struct ctl_table

На этом рисунке показана небольшая часть дерева, состоящего из объекта root_table и таблиц, на которые он указывает.

Объект struct ctl_table имеет следующие члены:

ctl_name. Целое число, которое однозначно обозначает вход таблицы (тем не менее, оно однозначно обозначает вход только внутри массива, в котором он находится); эти числа в разных массивах могут повторяться. Любой элемент массива уже имеет такой уникальный номер (его индекс в массиве), но это число не может применяться для данной цели, поскольку разработчики ядра обязаны обеспечить совместимость с последующими выпусками ядра на уровне двоичного кода. Настраиваемый параметр ядра, связанный со входом массива, в одной версии ядра, может исчезнуть в будущей версии ядра, поэтому, если бы параметры обозначались их индексами массива, то повторное использование позиции устаревшего элемента массива могло бы нарушить работу программ, которые не были перетранслированы под новое ядро. Со временем, массивы стали бы забиты неиспользуемыми входами, которые просто занимали бы место ради обратной совместимости. Вместо этого, в данном подходе просто «неэкономно» используются целые числа, в которых никогда нет недостатка. (С другой стороны, поиск становится медленнее, поскольку при таком методе нельзя просто использовать индекс массива.)


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

procname. Короткое, предназначенное для восприятия человеком имя файла для соответствующего входа под каталогом /proc/sys.

data. Указатель на данные, связанные с этим входом таблицы. Он обычно указывает на данные типа int или char (и, безусловно, указатель на char — это строка).

maxlen. Максимальное число байтов, которые могут быть считаны или записаны в член data. Например, если data указывает на один элемент типа int то maxlen должен быть равен sizeof(int).

mode. Биты прав доступа к файлу в стиле Unix для файла (или каталога) /proc, соответствующего этому входу. Для описания этого члена нужно сделать краткий экскурс в мир файловых систем. Как и в других реализациях Unix, в Linux используется три набора по три бита в каждом для регистрации прав доступа к файлу (в листинге, который выдает команда ls -l, они обозначаются в виде трех групп, состоящих из символов r, w и х); см. рис. 11.2. Они занимают нижние 9 битов члена mode. В файловой системе оставшиеся биты параметра mode файла предназначены для других целей, например, для слежения за тем, является ли файл обычным файлом (если да, то устанавливается бит 16), каталогом (бит 15), выполнимой программой, для которой установлены права setuid или setgid (биты 12 и 11), и так далее. Однако для материала настоящей главы эти прочие биты не имеют значения.



Рис. 11.2. Биты режима доступа к файлу

В результате, в сочетании с членом mode можно часто видеть восьмеричные константы 004, 002 и 001, которые предназначены, соответственно, для проверки битов чтения (r), записи (w) и выполнения (х), возможно, после сдвига члена mode для получения требуемого набора из трех битов. В конечном итоге, этот сдвиг и проверка выполняются в функции test_perm, строка .



Обратите внимание, что если вход таблицы имеет значение maxlen, равное 0, то он фактически не подлежит ни чтению, ни записи, независимо от значения его члена mode.

child. Указатель на дочернюю таблицу, если это — вход типа каталога. В этом случае с самим входом не связаны никакие данные, поэтому член data будет иметь значение NULL, a maxlen будет равен 0.

proc_handler. Указатель на функцию, которая фактически читает или пишет член data; он используется при чтении или записи данных с применением файловой системы /proc. Таким образом, член data может указывать на данные любого типа, а корректную работу с ними обеспечивает функция proc_handler. В качестве proc_handler обычно применяются функции proc_dostring (строка ) или proc_dointvec (строка ); эти и другие часто используемые функции рассматриваются далее в настоящей главе. (Безусловно, может применяться любая функция с правильным прототипом.) Для входов типа каталога член proc_handler имеет значение NULL.

strategy. Указатель на другую функцию, которая фактически выполняет чтение или запись в члене data; именно эта функция используется при чтении или записи с помощью системного вызова sysctl. Обычно это — функция sysctl_string (строка ), но может также применяться функция sysctl_intvec (строка ); обе эти функции рассматриваются далее в этой главе. По определенным причинам большинство настраиваемых параметров ядра подлежат изменению через интерфейс /proc, а не через системный вызов sysctl, поэтому этот указатель чаще имеет значение NULL, а не иное значение.

de. Указатель на объект struct proc_dir_entry, используемый в коде файловой системы /proc для отслеживания файла или каталога в этой файловой системе. Если он отличен от NULL, то где-то под каталогом /proc зарегистрирован соответствующий объект struct ctl_table.

extra1 и extra2. Указатели на любые дополнительные данные, необходимые при обработке этого элемента таблицы. Они в настоящее время используются только для указания минимальных и максимальных значений некоторых целочисленных параметров.


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