it-swarm.com.ru

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

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

Однако проблема в том, что 2.6.30 не экспортирует sys_read(). Скорее это обернуто в SYSCALL_DEFINE3. Поэтому, если я использую его в своем модуле, я получаю следующие предупреждения:

WARNING: "sys_read" [xxx.ko] undefined!
WARNING: "sys_open" [xxx.ko] undefined!

Очевидно, что insmod не может загрузить модуль, потому что связывание не происходит правильно.

Вопросы:

  • Как читать/писать в ядре после 2.6.22 (где sys_read()/sys_open() не экспортируются)?
  • В общем, как использовать системные вызовы, заключенные в макрос SYSCALL_DEFINEn() изнутри ядра?
84
Methos

Вы должны знать, что вам следует избегать файлового ввода-вывода, когда это возможно. Основная идея состоит в том, чтобы пойти "на один уровень глубже" и вызвать функции уровня VFS вместо обработчика syscall напрямую:

Включает в себя:

#include <linux/fs.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/buffer_head.h>

Открытие файла (аналогично открытию):

struct file *file_open(const char *path, int flags, int rights) 
{
    struct file *filp = NULL;
    mm_segment_t oldfs;
    int err = 0;

    oldfs = get_fs();
    set_fs(get_ds());
    filp = filp_open(path, flags, rights);
    set_fs(oldfs);
    if (IS_ERR(filp)) {
        err = PTR_ERR(filp);
        return NULL;
    }
    return filp;
}

Закрыть файл (аналогично close):

void file_close(struct file *file) 
{
    filp_close(file, NULL);
}

Чтение данных из файла (аналогично pread):

int file_read(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) 
{
    mm_segment_t oldfs;
    int ret;

    oldfs = get_fs();
    set_fs(get_ds());

    ret = vfs_read(file, data, size, &offset);

    set_fs(oldfs);
    return ret;
}   

Запись данных в файл (аналог pwrite):

int file_write(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) 
{
    mm_segment_t oldfs;
    int ret;

    oldfs = get_fs();
    set_fs(get_ds());

    ret = vfs_write(file, data, size, &offset);

    set_fs(oldfs);
    return ret;
}

Синхронизация изменений файла (аналогично fsync):

int file_sync(struct file *file) 
{
    vfs_fsync(file, 0);
    return 0;
}

[Edit] Первоначально я предложил использовать file_fsync, который отсутствует в более новых версиях ядра. Спасибо бедному парню, предложившему изменение, но чье изменение было отклонено. Редактирование было отклонено, прежде чем я смог его просмотреть.

109
dmeister

Начиная с версии 4.14 ядра Linux, функции vfs_read и vfs_writeбольше не экспортируются для использования в модулях. Вместо этого предоставляются функции исключительно для доступа к файлам ядра:

# Read the file from the kernel space.
ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos);

# Write the file from the kernel space.
ssize_t kernel_write(struct file *file, const void *buf, size_t count,
            loff_t *pos);

Кроме того, filp_open больше не принимает строку пользовательского пространства, поэтому его можно использовать для доступа к ядру напрямую (без использования set_fs).

8
Tsyvarev