it-swarm.com.de

Wie erstelle ich einen Geräteknoten aus dem init_module-Code eines Linux-Kernelmoduls?

Ich schreibe ein Modul für den Linux-Kernel und möchte einige Geräteknoten in der init-Funktion erstellen

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

Ich möchte auch, dass der Kernel meinem ersten Knoten eine untergeordnete Nummer zuweist, und dann werde ich die untergeordneten Nummern der anderen Knoten selbst zuweisen.

Wie kann ich das im Code machen. Ich möchte mit mknod keine Geräte aus der Shell erstellen

45
Alptugay

Um mehr Kontrolle über die Gerätenummern und die Geräteerstellung zu haben, können Sie die folgenden Schritte ausführen (anstelle von register_chrdev()):

  1. Rufen Sie alloc_chrdev_region() auf, um eine Haupt- und eine Reihe von Nebennummern zu erhalten, mit denen Sie arbeiten können.
  2. Erstellen Sie mit class_create() eine Geräteklasse für Ihre Geräte.
  3. Rufen Sie für jedes Gerät cdev_init() und cdev_add() auf, um das Zeichengerät zum System hinzuzufügen.
  4. Rufen Sie für jedes Gerät device_create() auf. Infolgedessen erstellt dev unter anderem Geräteknoten für Ihre Geräte. Keine Notwendigkeit für mknod oder dergleichen. Mit device_create() können Sie auch die Namen der Geräte steuern.

Es gibt wahrscheinlich viele Beispiele dafür im Internet, eines davon ist hier .

72
Eugene
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
Edwin Jose

Minimales lauffähiges Beispiel

Aus anderen Antworten minimiert. GitHub upstream mit Testaufbau.

#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");