Невозможно создать каталоги в / pro c из пользовательского модуля ядра - PullRequest
1 голос
/ 02 апреля 2020

В каталоге / pro c пользовательский модуль должен создать два каталога lkm и mem , чтобы получить иерархию типа / proc / lkm / mem,

Простой рефакторинг теперь нарушил то, что работало без очевидной причины.

После рефакторинга модуль больше не создает иерархию / proc / lkm / mem . Он только создает lkm и затем останавливается. В кольцевом буфере ядра нет сообщений. Мне было интересно, что я порвал с этим рефакторингом? Я надеюсь, что вы можете помочь мне найти проблему.

Ручные тесты были выполнены с запущенной fre sh VM и с обычным insmod / rmmod и следующими версиями:

  • Ядро: 5.3.0 (x86_64)
  • G CC: 9.2.1 20191008 (Ubuntu 9.2.1-9ubuntu2)
  • Распространение: Ubuntu 19.10, eoan

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

Заранее спасибо:)

Оригинальный код предшествующий на рефакторинг

static int __init lkm_mem_init(void)
{

    lkm_proc_parent = proc_mkdir(LKM_PROC_PARENT, NULL);

    if (lkm_proc_parent == NULL) {
        printk(KERN_ERR "lkm_mem: Failed to create parent /proc/%s for lkm.\n",
        LKM_PROC_PARENT);

        return 1;
    }

    mem_proc_parent = proc_mkdir(LKM_MEM_PROC_PARENT, lkm_proc_parent);

    if (mem_proc_parent == NULL) {
        printk(KERN_ERR
        "lkm_mem: Failed to create parent /proc/%s/%s for mem.\n",
        LKM_PROC_PARENT, LKM_MEM_PROC_PARENT);

        return 1;
    }

    // ...
}

Рефакторированный код

static int __init lkm_mem_init(void)
{

    lkm_proc_mkdir(lkm_proc_parent, LKM_PROC_PARENT, NULL);
    lkm_proc_mkdir(mem_proc_parent, LKM_MEM_PROC_PARENT, lkm_proc_parent);

    // ...
}

void lkm_proc_mkdir(struct proc_dir_entry *entry, const char *name,
            struct proc_dir_entry *parent)
{
    entry = proc_mkdir(name, parent);

    if (entry == NULL) {
        printk(KERN_ERR
               "lkm_mem: Failed to create parent %s in proc.\n",
               name);

        // todo: How to abort loading module in gentle way?
    }
}

// ...

Минимальный исходный код

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Thomas Piekarski");
MODULE_DESCRIPTION("Exposing separated memory and swap statistics to /proc");
MODULE_VERSION("0.1");

#define LKM_PROC_PERMISSION 0444
#define LKM_PROC_PARENT "lkm"
#define LKM_MEM_PROC_PARENT "mem"
#define LKM_MEM_PROC_TOTAL_ENTRY "total"
#define LKM_MEM_PROC_FREE_ENTRY "free"

struct sysinfo si;
struct proc_dir_entry *lkm_proc_parent;
struct proc_dir_entry *mem_proc_parent;
struct proc_dir_entry *mem_proc_total_entry;
struct proc_dir_entry *mem_proc_free_entry;

static int lkm_value_show(struct seq_file *seq, void *v)
{
    seq_put_decimal_ull(seq, "", *(unsigned long *)seq->private);
    seq_putc(seq, '\n');

    return 0;
}

void lkm_proc_create_single_data(struct proc_dir_entry *entry,
                 unsigned long *value, const char *name)
{
    entry = proc_create_single_data(name, LKM_PROC_PERMISSION,
                    mem_proc_parent, lkm_value_show, value);

    if (entry == NULL) {
        printk(KERN_ERR "lkm_mem: Failed to create /proc/%s/%s/%s.\n",
               LKM_PROC_PARENT, LKM_MEM_PROC_PARENT, name);
    }
}

void lkm_proc_mkdir(struct proc_dir_entry *entry, const char *name,
            struct proc_dir_entry *parent)
{
    entry = proc_mkdir(name, parent);

    if (entry == NULL) {
        printk(KERN_ERR
               "lkm_mem: Failed to create parent %s in proc.\n",
               name);
    }
}

void lkm_remove_proc_entry(struct proc_dir_entry *entry, const char *name,
               struct proc_dir_entry *parent)
{
    if (entry != NULL) {
        remove_proc_entry(name, parent);
    }
}

static int __init lkm_mem_init(void)
{
    lkm_proc_mkdir(lkm_proc_parent, LKM_PROC_PARENT, NULL);
    lkm_proc_mkdir(mem_proc_parent, LKM_MEM_PROC_PARENT, lkm_proc_parent);

    si_meminfo(&si);

    lkm_proc_create_single_data(mem_proc_total_entry, &si.totalram,
                    LKM_MEM_PROC_TOTAL_ENTRY);

    lkm_proc_create_single_data(mem_proc_free_entry, &si.freeram,
                    LKM_MEM_PROC_FREE_ENTRY);

    return 0;
}

static void __exit lkm_mem_exit(void)
{
    lkm_remove_proc_entry(mem_proc_total_entry, LKM_MEM_PROC_TOTAL_ENTRY,
                  mem_proc_parent);

    lkm_remove_proc_entry(mem_proc_free_entry, LKM_MEM_PROC_FREE_ENTRY,
                  mem_proc_parent);

    lkm_remove_proc_entry(mem_proc_parent, LKM_MEM_PROC_PARENT,
                  lkm_proc_parent);

    lkm_remove_proc_entry(lkm_proc_parent, LKM_PROC_PARENT, NULL);
}

module_init(lkm_mem_init);
module_exit(lkm_mem_exit);

Makefile

ccflags-y := -Wall

obj-m += lkm_device.o lkm_mem.o lkm_parameters.o lkm_proc.o lkm_sandbox.o lkm_skeleton.o

all:
    $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
    $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Редактирование - Добавлены URL-адреса для хранилища, выпуска и фиксации

1 Ответ

2 голосов
/ 02 апреля 2020
struct proc_dir_entry *lkm_proc_parent;
struct proc_dir_entry *mem_proc_parent;

static int __init lkm_mem_init(void)
{

lkm_proc_parent здесь NULL ...

    lkm_proc_mkdir(lkm_proc_parent, LKM_PROC_PARENT, NULL);

и все равно NULL here, поскольку, конечно, аргументы функции в C передаются по значению.

    lkm_proc_mkdir(mem_proc_parent, LKM_MEM_PROC_PARENT, lkm_proc_parent);

Так что это звонит proc_mkdir("mem", NULL). Вы, вероятно, заметите, что каталог /proc/mem создан.

    // ...
}

Между тем:

void lkm_proc_mkdir(struct proc_dir_entry *entry, const char *name,
            struct proc_dir_entry *parent)
{
    entry = proc_mkdir(name, parent);

    if (entry == NULL) {
        printk(KERN_ERR
               "lkm_mem: Failed to create parent %s in proc.\n",
               name);
    }
}

Значение, возвращаемое proc_mkdir, теряется при возврате этой функции, поскольку Вы только назначили его одному из аргументов функции, который, конечно, является локальным для функции. Опять же, аргументы передаются по значению!

Похоже, вы, вероятно, хотите от lkm_proc_mkdir до вернуть a struct proc_dir *, вместо того, чтобы принимать один в качестве аргумента. Или, возможно, вы хотели, чтобы первым аргументом был struct proc_dir **, но мне кажется, что это хуже стиля.

...