Получил NOTTY для ramfs ядра Linux с unlocked_ioctl

#c #linux #linux-kernel #filesystems #ioctl

Вопрос:

Я хочу добавить настраиваемую операцию файловой системы для ramfs ядра ioctl (т. Е. unlocked_ioctl in struct file_operations ). Что я сделал, так это скопировал код ramfs, переименовал .name в «myramfs», добавил функцию монтирования в .mount of struct file_system_type . Таким образом, я мог бы смонтировать «myramfs» в каталоге. Затем я создал функцию ioctl unlocked_ioctl , и в основном эта функция теперь предназначена только для тестирования и выполнения простого переключения…case и printk. Я определил две команды ioctl с помощью _IO . Я уверен, что функциональные возможности «myramfs» без ioctl работают должным образом.

Вот несколько фрагментов кода:

myramfs.c (код модуля ramfs)

 #include "myioctl.h"
// Only for testing purpose
static long myramfs_unlocked_ioctl(struct file *f,
                unsigned int cmd,
                unsigned long arg)
{
    switch (cmd) {
        case IOCTL_NUM1:
            printk(KERN_INFO "Call by IOCTL_NUM1n");
            break;
        case IOCTL_NUM2:
            printk(KERN_INFO "Call by IOCTL_NUM2n");
            break;
        default:
            printk(KERN_INFO "Call by Defaultn");
            break;
    }
    return 0;
}


const struct file_operations ramfs_file_operations = {
  ...
  .unlocked_ioctl = myramfs_unlocked_ioctl,
};
 

myioctl.h (самостоятельный файл заголовка ioctl)

 #include <linux/ioctl.h>
#define IOC_CODE    '1'
#define IOC_NO(x)   (IOC_CODE   (x))
#define MY_IOC(n)   _IO(IOC_CODE, IOC_NO(n))
#define IOCTL_NUM1  MY_IOC(1)
#define IOCTL_NUM2  MY_IOC(2)
 

Я написал программу для тестирования драйвера C в пространстве пользователя, чтобы вызвать ioctl «myramfs».:
test.c (программа драйвера пользовательского пространства для вызова ioctl и надежды получить информацию о печати в dmesg)

 #include <sys/ioctl.h>
#include "myioctl.h"
...
int dirfd;
//mp is the pathname of myramfs mountpoint
dirfd = open(mp, O_RDONLY | __O_DIRECTORY);
if (dirfd < 0) {
    exit(1);
}

int ret;
ret = ioctl(dirfd, VERIFS_CHECKPOINT, (void *)arg); // Got ENOTTY in this statement
 

Когда я позвонил ioctl в пространство пользователя, я получил errno = 25 (ENOTTY), что означает неподходящий ioctl для устройства. Я подозреваю, что это связано с тем, что я использовал точку монтирования fd в качестве первого аргумента пользовательского пространства ioctl вместо устройства fd. Но ramfs не нуждается в поддержке устройством, поэтому я не могу использовать device fd в качестве аргумента ioctl. Я не уверен, в чем проблема и правильно ли я реализовал ioctl для ramfs. Не могли бы вы, пожалуйста, помочь с этой ошибкой NOTTY в программе пользовательского драйвера? Спасибо вам за вашу помощь!

Комментарии:

1. Вы добавляете метод unlocked_ioctl в структуру ramfs_file_operations , который, согласно его названию, предназначен только для обычных файлов . Но вы, пользовательская космическая программа, пытаетесь работать с каталогом .

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

3. @Tsyvarev Большое тебе спасибо. Я попытался создать файл в точке монтирования myramfs, затем получить этот файл fd open и ввести его в ioctl качестве аргумента. Теперь это работает, и я могу получить ожидаемый вывод ядра. Интересно, нужно ли мне создавать файл, прежде чем делать ioctl это в пользовательском пространстве. Могу ли я запросить ioctl чистую файловую систему без какого-либо обычного файла в ней?

4. @старк, Спасибо. Похоже, что ramfs не требует устройства при монтаже, и я не знаю, как сопоставить устройство для ramfs. Есть идеи?

5. Вы также можете добавить ioctl для каталогов. Вместо назначения amp;simple_dir_operations создать свои собственные файловые операции для каталога и добавить unlocked_ioctl в него.