Comment créer un nœud de périphérique à partir du code du module init d'un module du noyau Linux?

J'écris un module pour le noyau linux et je veux créer des nœuds de périphérique dans la fonction init

int init_module(void)
{
    Major = register_chrdev(0, DEVICE_NAME, &fops);
 // Now I want to create device nodes with the returned major number
}

Je veux aussi que le noyau attribue un nombre mineur à mon premier nœud, puis j'attribuerai les numéros mineurs des autres nœuds par moi-même.

Comment puis-je faire cela dans le code. Je ne veux pas créer de périphériques à partir du shell en utilisant mknod

41

3 réponses

Pour avoir plus de contrôle sur les numéros de périphérique et la création de périphérique, vous pouvez effectuer les étapes suivantes (au lieu de register_chrdev()):

  1. appelez alloc_chrdev_region() pour obtenir un nombre majeur et une plage de nombres mineurs avec lesquels travailler.
  2. créez une classe de périphérique pour vos périphériques avec class_create().
  3. , Pour chaque appareil, appelez - cdev_init() et cdev_add() pour ajouter le caractère périphérique du système.
  4. , Pour chaque appareil, appelez - device_create(). En conséquence, entre autres choses, Udev créera des nœuds de périphérique pour vos appareils. Pas besoin de mknod ou similaire. device_create() vous permet également de contrôler les noms de périphériques.

, Il existe probablement de nombreux exemples sur le Net, l'un d'eux est ici.

68
répondu Eugene 2015-06-10 07:53:34
static int __init ofcd_init(void) /* Constructor */
{
    printk(KERN_INFO "Welcome!");
    if (alloc_chrdev_region(&first, 0, 1, "char_dev") < 0)  //$cat /proc/devices
    {
        return -1;
    }
    if ((cl = class_create(THIS_MODULE, "chardrv")) == NULL)    //$ls /sys/class
    {
        unregister_chrdev_region(first, 1);
        return -1;
    }
    if (device_create(cl, NULL, first, NULL, "mynull") == NULL) //$ls /dev/
    {
        class_destroy(cl);
        unregister_chrdev_region(first, 1);
        return -1;
    }
    cdev_init(&c_dev, &fops);
    if (cdev_add(&c_dev, first, 1) == -1)
    {
        device_destroy(cl, first);
        class_destroy(cl);
        unregister_chrdev_region(first, 1);
        return -1;
    }
    return 0;
}
12
répondu Edwin Jose 2013-09-03 14:24:04

Minimum praticable exemple

Réduit à partir d'autres réponses. GitHub amont avec configuration de test.

#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/fs.h> /* register_chrdev, unregister_chrdev */
#include <linux/module.h>
#include <linux/seq_file.h> /* seq_read, seq_lseek, single_release */

#define NAME "lkmc_character_device_create"

static int major = -1;
static struct cdev mycdev;
static struct class *myclass = NULL;

static int show(struct seq_file *m, void *v)
{
    seq_printf(m, "abcd");
    return 0;
}

static int open(struct inode *inode, struct file *file)
{
    return single_open(file, show, NULL);
}

static const struct file_operations fops = {
    .llseek = seq_lseek,
    .open = open,
    .owner = THIS_MODULE,
    .read = seq_read,
    .release = single_release,
};

static void cleanup(int device_created)
{
    if (device_created) {
        device_destroy(myclass, major);
        cdev_del(&mycdev);
    }
    if (myclass)
        class_destroy(myclass);
    if (major != -1)
        unregister_chrdev_region(major, 1);
}

static int myinit(void)
{
    int device_created = 0;

    /* cat /proc/devices */
    if (alloc_chrdev_region(&major, 0, 1, NAME "_proc") < 0)
        goto error;
    /* ls /sys/class */
    if ((myclass = class_create(THIS_MODULE, NAME "_sys")) == NULL)
        goto error;
    /* ls /dev/ */
    if (device_create(myclass, NULL, major, NULL, NAME "_dev") == NULL)
        goto error;
    device_created = 1;
    cdev_init(&mycdev, &fops);
    if (cdev_add(&mycdev, major, 1) == -1)
        goto error;
    return 0;
error:
    cleanup(device_created);
    return -1;
}

static void myexit(void)
{
    cleanup(1);
}

module_init(myinit)
module_exit(myexit)
MODULE_LICENSE("GPL");
5