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

Parse_table


Функция parse_table ищет вход в дереве таблиц по аналогии с тем, как происходит поиск в дереве каталогов полностью квалифицированного имени файла. Идея состоит в следующем: поиск происходит вдоль массива данных типа int (массива name) с просмотром каждого элемента типа int в массиве ctl_table. Если будет обнаружено совпадение, выполняется рекурсивный просмотр соответствующей дочерней таблицы (если совпадающий вход представляет собой вход типа каталога); или выполняется чтение и/или запись входа (если это вход типа файла).

К некоторому удивлению, это начало цикла, который перебирает все элементы целочисленного массива name. Было бы более привычно, если бы все, начиная с этой строки и кончая строкой , было заключено в цикл for, который мог бы начинаться примерно так:

for (; nlen; ++name, --nlen, table = table->child)

(Здесь также нужно было бы удалить строки и и заменить строки с по оператором break.) Возможно, фактически применяемая версия генерирует лучший объектный код.

Начинается цикл по всем входам таблицы в поиске входа с текущим значением name; цикл заканчивается по окончании таблицы (когда значение table->ctl_name становится равным 0) или после того, как будет найден и обработан указанный вход таблицы.

Считывает текущий вход массива name в переменную n, чтобы его можно было сверить со значением ctl_name в текущем входе таблицы. Поскольку значение name не меняется во внутреннем цикле, чтение этой переменной можно было бы вынести из цикла (то есть перенести в строку ) для небольшого ускорения.

Проверяет, совпадает ли имя текущего элемента ctl_table с искомым именем или имеет специальное «подстановочное» значение CTL_ANY (строка ). Назначение второй части не ясно, поскольку CTL_ANY в настоящее время в коде ядра нигде не используется. Может быть применение этого значения запланировано на будущее; автор не думает, что оно осталось от прошлого, поскольку значение CTL_ANY не использовалось и в ядре 2.0, и весь интерфейс sysctl относится только к проекту разработок, который предшествовал версии 2.0.


Если этот элемент таблицы имеет дочерний элемент, то он является «каталогом».

В соответствии со стандартными правилами поведения Unix, выполняется проверка бита х (выполнимый) каталога для определения того, следует ли разрешить текущему процессу войти в него. Обратите внимание, что это происходит во многом аналогично тому, что принято в файловой системе, хотя этот интерфейс (/proc) не является интерфейсом файловой системы. Это сделано для того, чтобы оба интерфейса к настраиваемым параметрами ядра давали единообразные результаты, поскольку было бы очень удивительно, если бы один и тот же пользователь имел право изменять какой-то параметр ядра через один интерфейс, но не через другой.

Если данный вход таблицы содержит strategy-функцию, может потребоваться отменить это решение, которое позволяет процессу войти в каталог. Выполняется обращение за консультацией к strategy-функции, и если она возвращает ненулевое значение, прерывается весь поиск.

Выполнен вход в каталог. Это фактически приводит к продолжению внешнего цикла и к переходу в нем к следующему компоненту имени.

Этот узел таблицы представляет собой лист-узел, а это значит, что найден параметр ядра. Обратите внимание, что функция не утруждает себя проверкой того, находится ли массив name в его последнем элементе (то есть того, равно ли теперь значение nlen единице), хотя можно утверждать, что иная ситуация представляла бы собой своего рода ошибку. Так или иначе, функция do_sysctl_strategy (строка ) получает поручение выполнить чтение и/или запись текущего элемента таблицы.

Массив name не был пуст, но его элементы были исчерпаны до того, как был найден лист-узел. Функция parse_table возвращает ошибку ENOTDIR в качестве сигнала о неудаче при поиске указанного узла. Кстати, обратите внимание на лишнюю точку с запятой в предыдущей строке.


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