Как обращаться с устройством с неизвестным второстепенным номером?

#c #linux #linux-kernel #linux-device-driver

Вопрос:

у меня есть задача: создать простое символьное устройство с основным номером = 255 и печатать «Привет, мир» каждый раз, когда оно открывается. Это действительно простая задача, но я не знаю, как обращаться с устройством с неизвестным второстепенным номером. Я могу создать массив из 256 элементов структуры моего устройства и связать его с номером узла (255, i). Но это не может быть оптимальным, потому что в памяти имеется 255 неиспользуемых объектов структур. Итак, как я могу обращаться с устройством с известным основным и неизвестным второстепенным номером?

 #include <linux/init.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/slab.h>

MODULE_LICENSE("GPL");

static struct _device
{
    size_t openCount, totalDataWritten;
    struct cdev c_dev;
    dev_t deviceNumber;
};


static struct _device *myDevice;

static int devOpen(struct inode * n, struct file * f)
{
    myDevice->openCount  ;          
    return 0;
}

static ssize_t devWrite(struct file * n, char const __user * c, size_t size, loff_t *l)
{
    myDevice->totalDataWritten  = size;
    return size;
}

static ssize_t devRead(struct file *fp, char __user *buf, size_t size, loff_t *off)
{
    char *tmpbuf = (char*) kmalloc(size, GFP_KERNEL);
    sprintf(tmpbuf,"%i %in", myDevice->openCount, myDevice->totalDataWritten);
    return size - copy_to_user(buf, tmpbuf, size);
}

static struct file_operations devOPS = 
{
    .owner = THIS_MODULE,
    .open = devOpen,
    .write = devWrite,
    .read = devRead,        
}; 

static const int major = 255, minor = 0;
static dev_t devID;
static const char *name = "solution_node";

static int __init deviceInit(void)
{
    myDevice = (struct _device *) kmalloc(sizeof(struct _device), GFP_KERNEL);
    devID = MKDEV(major, minor);

    if (register_chrdev_region(devID, 1, name) != 0)
    {
        return -1;
    }

    cdev_init(amp;myDevice->c_dev, amp;devOPS);
    myDevice->c_dev.owner = THIS_MODULE;
    myDevice->c_dev.ops = amp;devOPS;
    myDevice->openCount = 0;
    myDevice->totalDataWritten = 0;
    myDevice->deviceNumber = MKDEV(major, minor   1);

    if (cdev_add(amp;myDevice->c_dev, myDevice->deviceNumber, 1))
    {
        return -2;
    }   
        
    return 0;
}

static void __exit deviceExit(void)
{
    cdev_del(amp;myDevice->c_dev);
    unregister_chrdev_region(devID, 1);
    return;
}

module_init(deviceInit);
module_exit(deviceExit);
 

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

1. Покажите нам код, который у вас есть до сих пор, иначе вам будет трудно помочь. В чем именно заключается проблема? Когда вы создаете устройство соответствующим образом, вы можете запросить автоматическое присвоение второстепенного номера, и ядро выдаст вам его (кстати, это также верно для основного номера).

2. myDevice->deviceNumber = MKDEV(major, minor 1); выглядит неправильно. Он находится за пределами зарегистрированного региона chrdev. Может быть, вы имели в виду myDevice->deviceNumber = MKDEV(major, minor); ?

3. Вы не должны использовать основной номер 255, потому что он зарезервирован.

4. Произошла утечка памяти devRead() .

5. @0andriy, @ianAbbott, извините, ребята, похоже, я не понял функцию cdev_add ().