сложные задачи — простые решения


Start of topic | Skip to actions

Использование Debugfs для отладки модулей ядра linux

Введение

В функциях модулей ядра, время выполнения которых критично, использование отладочного вывода с помощью printk зачастую невозможно. Однако наблюдать за происходящими событиями в этой функции можно. Для этого предназначена файловая система debugfs. Перед вызовом функции нужно только создать необходимое количество файлов и у нас появляется возможность наблюдать за работой функции прямо из user space. А если требуется, то можно прямо на ходу управлять функцией.

Давайте посмотрим на то, как просто это делается.

Внимание! Приведенные примеры актуальны для ядра linux версии 2.6.17. В более новых версиях ядра могут быть модификации.

Что такое debugfs?

Debugfs - это виртуальная файловая ситема, похожая на /sysfs и /procfs, но с минимальным набором функций. Debugfs позволяет очень просто смотреть/менять значение любой переменной прямо во время работы модуля, в котором эта переменная присутствует. Для этого в debugfs создается файл, содержимое которого и есть значение заданной переменной. Таким образом, чтобы иметь возможность управлять какой-либо переменной нам нужно сделать всего несколько шагов:

  1. создать директорию в debugfs (это не обязательно, но так может оказаться удобней);
  2. создать в этой директории файл, который и будет отвечать за нашу переменную. В API debugfs уже есть готовые решения для переменных типа u8/u16/u32.

Все callback`и для чтения или записи в файл них уже реализованы в ядре. Нам лишь остается использовать готовые фукнции для создания и удаления файлов.

Конфигурация ядра

Для работы с debugfs необходимо, чтобы ядро было собрано с опциями:

CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_FS=y

Чтобы проверить, включена ли debugfs в ядре, можно сделать так:

$ cat /proc/filesystems 
nodev   sysfs
nodev   rootfs
nodev   bdev
nodev   proc
nodev   debugfs
nodev   sockfs
nodev   pipefs
nodev   futexfs
nodev   tmpfs
nodev   eventpollfs
nodev   devpts
nodev   ramfs
nodev   jffs2

Если видим в списке debugfs - все хорошо. Далее необходимо подмонтировать debufs:

$ mount -t debugfs none_debugfs /proc/sys/debug

Пример использования debugfs

Рассмотрим пример простого модуля с использованием debugfs:

...
#include <linux/debugfs.h>
...
static struct dentry* dbg_dir = NULL;
static struct dentry* dbg_entry = NULL;

u32 tst_val = 0;

// инициализация модуля
static int init(void)
{
  // Создаем директорию в debugfs
  dbg_dir = debugfs_create_dir("dir", NULL);
  if (!dbg_dir) {
    return -EFAULT;
  }

  // Создаем файл tst в директории dir. При создании передаем
  // адрес переменной tst_val, которую мы хотим изменять из userspace
  dbg_entry = debugfs_create_u32("tst", S_IRUGO, dbg_dir, &tst_val);
  if (!dbg_entry) {
    debugfs_remove(dbg_dir);
    return -EFAULT;
  }

  return 0;
}

// деинициализация модуля
static void cleanup(void)
{
  // перед выходом выведем значение тестовой переменной, 
  // чтобы убедиться, что она действительно изменилась 
  printk("val: %u\n", tst_val);

  // Перед выходом нужно удалить сначала файл, 
  // а затем и его директорию-parent`a
  debugfs_remove(dbg_dir);
  debugfs_remove(dbg_entry);
}

Загрузим наш модуль и посмотрим, что получилось:

# загружаем модуль
$ insmod b4_debug.ko

# в каталоге dir появился файл tst
$ ls /proc/sys/debug/dir/ 
tst

# считываем значение переменной tst_val
$ cat /proc/sys/debug/dir/tst
0

# записываем новое значение
$ echo 4 > /proc/sys/debug/dir/tst

# проверяем
$ cat /proc/sys/debug/b4/tst
4

Таким образом можно менять/смотреть любую переменную модуля ядра без особых усилий

Ссылки

  1. http://lwn.net/Articles/115405/

Юрий Людкевич, НТЦ Метротек.

© b4open, 2006