modulos modprobe lsmod compilar como comando cargar actualizar linux linux-kernel mknod

modprobe - ¿Cómo crear un nodo de dispositivo a partir del código init_module de un módulo del kernel de Linux?



como cargar un modulo en linux (3)

Para tener más control sobre los números de dispositivo y la creación del dispositivo, puede realizar los siguientes pasos (en lugar de register_chrdev() ):

  1. Llame a alloc_chrdev_region() para obtener un número mayor y un rango de números menores para trabajar.
  2. Crea una clase de dispositivo para tus dispositivos con class_create() .
  3. Para cada dispositivo, llame a cdev_init() y cdev_add() para agregar el dispositivo de caracteres al sistema.
  4. Para cada dispositivo, llame a device_create() . Como resultado, entre otras cosas, Udev creará nodos de dispositivo para sus dispositivos. No hay necesidad de mknod o similares. device_create() también le permite controlar los nombres de los dispositivos.

Probablemente hay muchos ejemplos de esto en la Red, uno de ellos está aquí .

Estoy escribiendo un módulo para el kernel de Linux y quiero crear algunos nodos de dispositivo en la función init

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

También quiero que el kernel asigne un número menor para mi primer nodo, y luego asignaré los números menores de los otros nodos por mi cuenta.

¿Cómo puedo hacer esto en el código. No quiero crear dispositivos desde la shell usando mknod


Ejemplo ejecutable mínimo

Minimizado de otras respuestas. GitHub upstream con configuración de prueba.

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


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; }