天天看點

26 register_chrdev函數

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

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 ?  : cd->major;
out:
    kobject_put(&cdev->kobj);
out2:
    kfree(__unregister_chrdev_region(cd->major, baseminor, count));
    return err;
}
           

/

register_chrdev函數把以前分開的做的申請裝置号,cdev_init, cdev_add等操作封裝起來,一個函數來完成.

用起來友善 ,但有局限性。它的次裝置号固定是從0開始, 裝置的個數固定為256個.

如都用這函數來實作裝置驅動,那主裝置就無法重用,盡管次裝置号可用範圍還有很大的空間.

如用于實作隻有一個同類裝置的驅動,隻用一個裝置号就可以,用這個函數就會多浪費裝置号.

如用于實作多于256個同類裝置的驅動時,裝置号不夠用.

這個函數其實常用于核心裡的中間層(把某類裝置驅動必用功能封裝成一種簡化的可共用的接口).

測試代碼, test.c:

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

#define MYMA 4095

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

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

//編譯加載驅動後,隻要建立主裝置号為4095, 次裝置号為(0--255之間)的裝置檔案都可以調用驅動
           

繼續閱讀