简体   繁体   English

如何从Linux内核模块的init_module代码创建设备节点?

[英]How to create a device node from the init_module code of a Linux kernel module?

I am writing a module for the linux kernel and I want to create some device nodes in the init function 我正在为linux内核编写一个模块,我想在init函数中创建一些设备节点

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

I also want the kernel to assign a minor number for my first node, and then I will assign the other nodes' minor numbers by myself. 我还希望内核为我的第一个节点分配一个次要编号,然后我将自己分配其他节点的次要编号。

How can I do this in the code. 我怎么能在代码中执行此操作。 I dont want to create devices from the shell using mknod 我不想使用mknod从shell创建设备

To have more control over the device numbers and the device creation you could do the following steps (instead of register_chrdev() ): 要更好地控制设备编号和设备创建,您可以执行以下步骤(而不是register_chrdev() ):

  1. Call alloc_chrdev_region() to get a major number and a range of minor numbers to work with. 调用alloc_chrdev_region()以获取要使用的主要数字和一系列次要数字。
  2. Create device class for your devices with class_create() . 使用class_create()为您的设备创建设备类。
  3. For each device, call cdev_init() and cdev_add() to add the character device to the system. 对于每个设备,请调用cdev_init()cdev_add()以将字符设备添加到系统。
  4. For each device, call device_create() . 对于每个设备,请调用device_create() As a result, among other things, Udev will create device nodes for your devices. 因此,除其他外, Udev将为您的设备创建设备节点。 No need for mknod or the like. 不需要mknod等。 device_create() also allows you to control the names of the devices. device_create()还允许您控制设备的名称。

There are probably many examples of this on the Net, one of them is here . 网上可能有很多这样的例子, 其中一个在这里

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

Minimal runnable example 最小的可运行示例

Minimized from other answers. 最小化其他答案。 GitHub upstream with test setup. GitHub上游测试设置。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM