Как использовать оболочку больших двоичных объектов DebugFS в модуле ядра

Я пытаюсь найти самый быстрый способ перемещения больших данных из ядра в пространство пользователя. Прямо сейчас я пробую отладочные файлы GKH, но я изо всех сил пытаюсь заставить работать оболочку больших двоичных объектов.

Это то, что я получил до сих пор:

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/debugfs.h>

MODULE_AUTHOR("CREED0R");
MODULE_LICENSE("GPL");


struct dentry *dfs;
struct debugfs_blob_wrapper *myblob;

int my_init(void)
{
    int stats[10];
    int i;

    for (i = 0; i < 10; i++)
        stats[i] = i;

    myblob->data = (void *) stats;
    myblob->size = (unsigned long) 10;

    dfs = debugfs_create_blob("test", 0644, NULL, myblob);

    if (dfs == NULL) {
        printk("Could not create debugfs blob\n");
        return 1;
    }

    printk("DebugFS file created\n");

    return 0;
}


void my_exit(void)
{
    printk("DebugFS file deleted\n\n");
    debugfs_remove(dfs);
}


module_init(my_init);
module_exit(my_exit);

Он собирается, но если я запускаю insmod, мой экземпляр qemu ужасно умирает.

Не уверен, почему это так. Что мне не хватает?


person user2036087    schedule 02.02.2013    source источник
comment
Что касается способов передачи данных из пространства ядра в пространство пользователя, вы пробовали буферы mmapped или netlink? Они часто используются для этой цели, хотя их использование может быть несколько сложнее.   -  person Eugene    schedule 03.02.2013
comment
Как именно умирает? Не могли бы вы опубликовать здесь полученный вами отчет об ошибках ядра (если это ошибка)? Что касается кода, я не вижу, где именно находится структура, на которую указывает «myblob». Возможно, именно разыменование этого указателя вызывает сбой в my_init(). И, кстати, возвращать положительное значение из my_init() при ошибке, вероятно, не очень хорошая идея. IIRC, система будет считать, что в этом случае my_init() удалось. Обычной практикой является возврат отрицательного кода ошибки, например, -EINVAL, -ENOMEM и т. д.   -  person Eugene    schedule 03.02.2013
comment
См. также этот вопрос и комментарии к нему могут оказаться полезными.   -  person Eugene    schedule 03.02.2013


Ответы (1)


Спасибо за вашу помощь. Я просто забыл получить mem для blob-struct, поэтому установка указателя данных и размера неизбежно убила его.

Вот правильная версия, перекачивающая 32 КБ u32 из ядра в пользовательское пространство. Он собирается с ядром 2.6.32.38:

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/debugfs.h>

#define SIZE 8192

MODULE_AUTHOR("CREED0R");
MODULE_LICENSE("GPL");

struct dentry *dfs;
struct debugfs_blob_wrapper *myblob;

u32 *stats; /* our blob of data */

int my_init(void)
{
    int i;
    int stats_size;   /* size of our data */
    int struct_size;  /* size of the blob struct */

    struct_size = sizeof(struct debugfs_blob_wrapper);
    stats_size  = SIZE * sizeof(u32);


    /* get mem for data */
    stats = kmalloc(stats_size, GFP_KERNEL);

    if (stats == NULL) {
        printk("Could not allocate mem for data\n");
        return -ENOMEM;
    }


    /* fill datablob with dummy data */
    for (i = 0; i < SIZE; i++)
        stats[i] = i;


    /* get mem for blob struct and init */
    myblob = (struct debugfs_blob_wrapper *) kmalloc(struct_size, GFP_KERNEL);

    if (myblob == NULL) {
        printk("Could not allocate mem for blob\n");
        kfree(stats);
        return -ENOMEM;
    }


    /* only set data pointer and data size */
    myblob->data = (void *) stats;
    myblob->size = (unsigned long) stats_size;


    /* create pseudo file under /sys/kernel/debug/ with name 'test' */
    dfs = debugfs_create_blob("test", 0644, NULL, myblob);

    if (dfs == NULL) {
        printk("Could not create debugfs blob\n");
        kfree(stats);
        kfree(myblob);
        return -EINVAL;
    }

    printk("DebugFS file created\n");

    return 0;
}


void my_exit(void)
{
    printk("DebugFS file deleted\n\n");

    kfree(myblob);
    kfree(stats);

    debugfs_remove(dfs);
}


module_init(my_init);
module_exit(my_exit);
person user2036087    schedule 03.02.2013
comment
Какое значение ошибки подходит для последнего случая, когда файл не может быть создан? - person user2036087; 03.02.2013
comment
Функции debugfs_create_*() могут не работать по нескольким причинам. К сожалению, они не возвращают код ошибки, поэтому нет простого способа определить, почему они не справились, и нет абсолютно правильного кода ошибки, который возвращает ваша функция инициализации. Я полагаю, можно выводить сообщение об ошибке и возвращать что-то вроде -EINVAL или -EPERM, как вы делаете сейчас. - person Eugene; 03.02.2013
comment
Еще одно замечание: лучше освободить выделенную память до того, как ваша функция инициализации выйдет с кодом ошибки, в данном случае в обоих местах. Ядро не может освободить ее самостоятельно, поэтому память останется выделенной и недоступной для других компонентов пространства ядра, пока система не будет перезагружена. - person Eugene; 03.02.2013
comment
Спасибо, я это запомню; ) - person user2036087; 03.02.2013