Файловый ввод / вывод в модуле ядра Linux - PullRequest
19 голосов
/ 09 ноября 2008

Я пишу модуль ядра Linux, который должен открывать и читать файлы. Какой лучший способ сделать это?

Ответы [ 6 ]

31 голосов
/ 09 ноября 2008

Могу я спросить, почему вы пытаетесь открыть файл?

Мне нравится следить за развитием Linux (из любопытства, я не разработчик ядра, я занимаюсь Java), и я уже видел обсуждение этого вопроса раньше. Я смог найти LKML-сообщение об этом, в основном упомянув, что обычно это плохая идея. Я почти уверен, что LWN освещал это в прошлом году, но у меня проблемы с поиском статьи.

Если это частный модуль (например, для некоторого нестандартного оборудования и модуль не будет распространяться), то вы можете сделать это, но у меня сложилось впечатление, что если вы собираетесь отправить свой код на основную линию, это может быть не принято.

Эван Теран упомянул sysfs, что мне кажется хорошей идеей. Если вам действительно нужно делать что-то сложное, вы всегда можете создать новый ioctrls.

EDIT:

ОК, я нашел статью, которую искал, она из Linux Journal . Это объясняет, почему делать подобные вещи, как правило, является плохой идеей, а затем рассказывает, как именно это сделать.

9 голосов
/ 09 ноября 2008

при условии, что вы можете получить указатели на соответствующие указатели функций на системные вызовы open / read / close, вы можете сделать что-то вроде этого:

mm_segment_t fs = get_fs();
set_fs(KERNEL_DS);

fd = (*syscall_open)(file, flags, mode);
if(fd != -1) {
    (*syscall_read)(fd, buf, size);
    (*syscall_close)(fd);
}
set_fs(fs);

вам нужно будет создать указатели функций "syscall_*", которые я показал. Я уверен, что есть лучший способ, но я верю, что это сработает.

2 голосов
/ 09 ноября 2008

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

Существуют механизмы (например, netlink - или просто регистрация символьного устройства), позволяющие модулю ядра взаимодействовать с вспомогательным процессом в пользовательском пространстве. Этот вспомогательный процесс в пространстве пользователя может делать все, что захочет.

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

Это, вероятно, было бы лучше, чем пытаться открывать файлы в пространстве ядра.

Есть некоторые другие вещи, которые уже открывают файлы из пространства ядра, вы можете посмотреть их (на ум приходит драйвер цикла?).

1 голос
/ 13 ноября 2008

/ proc файловая система также хороша для частного использования и проста.
http://www.linuxtopia.org/online_books/Linux_Kernel_Module_Programming_Guide/x773.html

1 голос
/ 09 ноября 2008

Вы также можете найти некоторые сведения о sys_call_open в этом Руководстве по программированию модуля ядра Linux .

0 голосов
/ 05 декабря 2018

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

kernel_read_file_from_path(const char *path, void **buf, loff_t *size, loff_t max_size, enum kernel_read_file_id id)
Функция

, используемая кодом загрузчика прошивки, объявлена ​​в include/linux/fs.h. Эта функция возвращает отрицательное значение при ошибке.

Я не совсем уверен относительно точки переменной id в конце, если вы посмотрите на код, который на самом деле не используется, просто поместите что-то вроде READING_FIRMWARE (без кавычек).

buf не заканчивается нулем, вместо этого обратитесь к его размеру в size. Если вам нужно, чтобы он завершался нулем, создайте строку длиной size + 1 байт и скопируйте ее или переписайте функцию kernel_read_file() (используется kernel_read_file_from_path(), определенную в fs/exec.c) и добавьте ее в i_size, где память выделено. (Если вы хотите сделать это, вы можете переопределить функцию kernel_read_file() в вашем модуле с другим именем функции, чтобы избежать изменения всего ядра.)

Если вам нужно записать в файлы, есть функция kernel_write() (аналог kernel_read(), которая используется kernel_read_file() и, следовательно, также kernel_read_file_from_path()), но нет kernel_write_file() или * Функция 1026 *. Вы можете посмотреть код в файле fs/exec.c в дереве исходных текстов ядра Linux, где kernel_read_file() и kernel_read_file_from_path() определены для написания ваших собственных функций kernel_write_file() и kernel_write_file_from_path(), которые вы можете включить в свой модуль.

И, как всегда, с помощью этой функции вы можете сохранить содержимое файла в указателе символа вместо пустого указателя при помощи его приведения.

...