24 驅動裝置申請一體函式(register_chrdev)
阿新 • • 發佈:2018-11-25
驅動裝置申請一體函式(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