Это видеопоказывает пример модуля ядра Raspberry Pi Linux, который создает новое символьное устройство. Он использует API ядра register_chdev
. В комментарии к видео (я не могу сгенерировать прямую ссылку на него), что касается возвращаемого значения register_chdev
, автор заявляет:
Если возвращаемое значение не равно 0, номер устройства уже используется. Верхние 12 бит возвращаемого значения — это ваш основной номер устройства, нижние 20 бит — это дополнительный номер устройства.
Полагаю, что под «номер устройства уже используется» он подразумевает «ненулевой основной номер устройства, произвольно выбранный в модуле ядра, уже используется».
Несмотря на то, что несколько веб-страниц посвящены этому вопросу (официальный, затемВот этотиВот этот), я не нашел никакой информации об этом внутреннем подразделении возвращаемого значения.
Если я выбираю создать (с помощью модуля ядра) устройство с уже используемым старшим номером, ядро никогда его не примет и откажется регистрировать устройство. Это происходит как в случае, когда выбранный мной старший номер совпадает с номером блочного устройства, так и в случае, когда выбранный мной старший номер совпадает с номером символьного устройства. register_chdev
всегда возвращают отрицательное значение. В последнем случае вместо этого я ожидал положительного ненулевого возвращаемого значения, при этом старшие 12 бит представляют старший номер устройства, а нижние 20 бит представляют младший номер устройства (возможно, больше 0: если старший номер уже использовался, возможно, в системе уже было по крайней мере устройство, связанное с ним, с младшим номером 0).
Правда ли то, что говорится в комментарии на Youtube? Где я могу найти документацию по этому поводу?
У меня Raspbian 10, uname -a
показывает:
Linux raspberrypi 5.10.63-v7+ #1459 SMP Wed Oct 6 16:41:10 BST 2021 armv7l GNU/Linux
решение1
register_chrdev
сам по себе не документирован в ядре, ноего определение короткое:
static inline int register_chrdev(unsigned int major, const char *name,
const struct file_operations *fops)
{
return __register_chrdev(major, 0, 256, name, fops);
}
что по сути означает, что он звонит__register_chrdev
для регистрации major с полным диапазоном minors (256 minors, начиная с 0) и возврата результата этой функции. Последнее документируется как
Если
major
== 0 эта функция динамически выделит основной номер и вернет его номер.Если
major
> 0 эта функция попытается зарезервировать устройство с указанным старшим номером и вернет ноль в случае успеха.В случае возникновения ошибки возвращается значение -ve.
Нет положения для возврата несовершеннолетних, закодированных или иным образом. Цель этих функций — зарегистрировать мажор в любом случае, потенциально с подмножеством несовершеннолетних; а не с одним несовершеннолетним.
Theкодированиевступает в игру, когда драйвер устройства обрабатывает open
вызов или в любое другое время, когда ему нужно определить, какому младшему (и, возможно, старшему, если он обрабатывает несколько старших) соответствует данное устройство. Драйверу дается inode, который он должен обработать; для узла устройства, который включает номер устройства, который кодирует старший и младший.MAJOR
иMINOR
макросы, или начиная с инода,imajor
иiminor
функции следует использовать для извлечения значений.
Некоторые символьные устройства предлагают мультиплексирование поверх основных механизмов регистрации, описанных выше; см.Как один драйвер управляет всем этим различным оборудованием?для примера.