24 驱动设备申请一体函数(register_chrdev)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ForFuture_/article/details/79407216

驱动设备申请一体函数(register_chrdev)


register_chrdev函数把以前分开的做的申请设备号,cdev_init,cdev_add等操作封装起来,一个函数来完成。

用起来方便,但有局限性,它的次设备号固定是从0开始,设备的个数固定为256个。
如都用这函数来实现设备驱动,那主设备就无法重用,尽管次设备号可用范围还有很大的空间。
如用于实现只有一个同类设备的驱动,只用一个设备号就可以,用这个函数就会多浪费设备号。
如用于实现多于256个同类设备的驱动时,设备号不够用。


register_chrdev函数内部实现过程:

int __register_chrdev(unsigned int major, unsigned int baseminor,
                unsigned int count, const char *name,
                const struct file_operations *fops)
{
    struct char_device_struct *cd;
    struct cdev *cdev;
    int err = -ENOMEM;

    cd = __register_chrdev_region(major, baseminor, count, name); //申请设备号
    if (IS_ERR(cd))
        return PTR_ERR(cd);

    cdev = cdev_alloc(); //动态创建cdev对象并初始化list和kobj成员
    if (!cdev)
        goto out2;

    cdev->owner = fops->owner;
    cdev->ops = fops;
    kobject_set_name(&cdev->kobj, "%s", name);

    err = cdev_add(cdev, MKDEV(cd->major, baseminor), count); //增加cdev对象到内核里
    if (err)
        goto out;

    cd->cdev = cdev;

    return major ? 0 : cd->major;

out:
    kobject_put(&cdev->kobj);
out2:
    kfree(__unregister_chrdev_region(cd->major, baseminor, count));
    return err;
}

static inline int register_chrdev(unsigned int major, const char *name,
                            const struct file_operations *fops)
{
    return __register_chrdev(major, 0, 256, name, fops);
}

测试代码(test.c):

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

#define MYMA 1234

ssize_t myread(struct file *fl, char __user *buf, size_t len, loff_t *off)
{
    printk("in myread ...\n");
    return 0;
}

struct file_operations  fops = {
    .read = myread,
};

static int __init test_init(void)
{
    int ret;

    ret = register_chrdev(MYMA, "mydev", &fops);
    return ret;
}

static void __exit test_exit(void)
{
    unregister_chrdev(MYMA, "mydev");
}

module_init(test_init);
module_exit(test_exit);

MODULE_LICENSE("GPL");

编译加载驱动后,只要创建主设备号为1234,次设备号为(0到255之间)的设备文件都可以调用驱动。

如:mknod /dev/mydev c 1234 111

猜你喜欢

转载自blog.csdn.net/ForFuture_/article/details/79407216
24
今日推荐