LINUX.ORG.RU

Почему нельзя писать читать/писать файл из пространства/модуля ядра?


0

0

Была задача вести отдельный лог-файл для определенного драйвера. По умолчанию сообщения от него писались в системный лог с помощь функции printk, а хотелось чтобы сообщения от этого драйвера сохранялись бы в отдельный файл (/var/log/my_driver.log например). Я написал тестовый модуль, который при загрузке пишет в файл какую-то информацию. Но прочитал на одном англоязычном сайте, что так делать очень очень не рекомендуется. Вопрос: почему? Может кто ответит? Может у кого есть какие-нибудь идеи по этому поводу? Буду очень благодарен Вот код модуля: #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/proc_fs.h> #include <linux/sched.h> #include <linux/string.h> #include <linux/signal.h> //#include <linux/signalfd.h> #include <asm/unistd.h> #include <asm/siginfo.h> #include <asm/uaccess.h> #include <linux/syscalls.h> #include <linux/file.h> #include <linux/fs.h> #include <linux/fcntl.h>

MODULE_LICENSE("GPL");

static void write_file(char *filename, char *data) { struct file *file; loff_t pos = 0; int fd; mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); fd = sys_open(filename, O_WRONLY|O_CREAT, 0644); if (fd >= 0) { file = fget(fd); if (file) { vfs_write(file, data, strlen(data), &pos); fput(file); } sys_close(fd); } set_fs(old_fs); } //============================================================================= ======================== static int sys_calls_mod_init(void) { printk(KERN_INFO "sys_calls_mod init:\n"); write_file("/tmp/test", "bla-bla-bla\n"); return 0; } //============================================================================= ======================== static void sys_calls_mod_exit(void) { printk(KERN_ALERT "sys_calls_mod exit\n"); } //============================================================================= ======================== module_init(sys_calls_mod_init); module_exit(sys_calls_mod_exit);

anonymous

Может так код будет более читаемым :-)
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/signal.h>
//#include <linux/signalfd.h>
#include <asm/unistd.h>
#include <asm/siginfo.h>
#include <asm/uaccess.h>
#include <linux/syscalls.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/fcntl.h>

MODULE_LICENSE("GPL");

static void write_file(char *filename, char *data)
{
struct file *file;
loff_t pos = 0;
int fd;

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

fd = sys_open(filename, O_WRONLY|O_CREAT, 0644);
if (fd >= 0) {
file = fget(fd);
if (file) {
vfs_write(file, data, strlen(data), &pos);
fput(file);
}
sys_close(fd);
}
set_fs(old_fs);
}

//==================================
static int sys_calls_mod_init(void)
{
printk(KERN_INFO "sys_calls_mod init:\n");
write_file("/tmp/test", "Evil file.\n");
return 0;
}
//==================================
static void sys_calls_mod_exit(void)
{
printk(KERN_ALERT "sys_calls_mod exit\n");
}
//==================================
module_init(sys_calls_mod_init);
module_exit(sys_calls_mod_exit);

anonymous
()
Ответ на: комментарий от kranky

Гм, ну читать понятно почему нельзя. А писать? Почему нельзя писать? Или я туплю?

anonymous
()
Ответ на: комментарий от true_admin

true_admin, а как тогда настроить syslog, чтобы он сообщения именно от моего модуля собирал в нужный мне файл, а не писал туда все сообщения от ядра?

anonymous
()

1. нужно юзать не сисколы, а vfs функции (vfs_open, vfs_close, etc) - вобщем, мучай VFS подсистему.

2. и все же это тоже очень плохо, т.к. нарушается абстракция. вобщем-то, на этапе первичной отладки это несмертельно, но оставлять не стоит.

generatorglukoff ★★
()
Ответ на: комментарий от anonymous

а зачем? пиши что-то типа "<мой-аццки-крутой-модуль>: аццки-крутая-мессага", а потом use grep, Luke!

generatorglukoff ★★
()
Ответ на: комментарий от anonymous

1. /var/log может и не быть
2. /var/log может примаунчена по только чтению
3. /var/log может маунтится позже по сети
4. модуль должен содержать минимум кода, и policy/mechanism *должны* быть разделенны
5. для логирования есть уже готовая система (syslog)
6. изобретать велосипеды не нужно
7. из соображений портабельности/переносимости не нужно полагаться на то, что у всех пользователей будет достаточно места для твоего лога на разделе, и т.п.

anonymous
()
Ответ на: комментарий от anonymous

8. Если твоему модулю нужно работать с файлами - значит ты сделал херь, от неё нужно быстро избавиться и подумать, как сделать всё по-нормальному.

anonymous
()

ты можешь гарантировать, что реализованное тобой логирование будет неблокируемым?
для драйвера это критично

rei3er
()

если сильно хочется, то реализуй логирование (I/O) отдельным процессом ядра/тасклетом/отложенным действием/...
сам драйвер будет работать с кольцевым буфером (т. е без блокирования записи), который будет дампиться сабжем выше
это будет почти то же самое, что и printk() ;)

rei3er
()
Ответ на: комментарий от rei3er

Реализовал с помощью сислога (а точнее демона klogd), все работает. Спасибо всем

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.