1. 程式人生 > >24 驅動裝置申請一體函式(register_chrdev)

24 驅動裝置申請一體函式(register_chrdev)

驅動裝置申請一體函式(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