主要函数为my_cdev_init(),驱动启动部分可能不全
struct cdev {
struct kobject kobj; // 内嵌的内核对象.
struct module *owner; //该字符设备所在的内核模块的对象指针.
const struct file_operations *ops; //该结构描述了字符设备所能实现的方法,即file_operations.
struct list_head list; //用来将已经向内核注册的所有字符设备形成链表.
dev_t dev; //字符设备的设备号,由主设备号和次设备号构成.
unsigned int count; //隶属于同一主设备号的次设备号的个数.
} __randomize_layout;
=
struct my_cdev
{
int major;
dev_t cdevno;
struct cdev cdev;
struct device* sys_device;
struct class *class;
};
struct my_cdev g_my_cdev;
static const struct file_operations my_cdev_fops = {
.owner = THIS_MODULE,
.open = my_open,
.release = my_close,
.read = my_read,
.write = my_write,
};
int my_cdev_init()
{
struct my_cdev* cdev = &g_my_cdev;
dev_t dev;
if(cdev->sys_device)
{
return 0;
}
if(!cdev->major)
{
/*动态分配设备号*/
if(alloc_chrdev_region(&dev, 0, 255, "my_dev"))
{
printk("alloc_chrdev_region failed\n");
}
cdev->major = MAJOR(dev); /*dev: 0e f0 00 00*/
/*cdev->major: 00 00 00 ef*/
}
cdev->cdev.owner = THIS_MODULE;
if(kobject_set_name(&cdev->cdev.kobj, "cdev") < 0)
{
printk("cdev_add failed\n");
goto unregister_region;
}
cdev->cdevno = MKDEV(cdev->major,1);/*cdev->cdevno : 0e f0 00 01*/
cdev_init(&cdev->cdev, &my_cdev_fops);
/*加入到内核结构体cdev_map设备列表中*/
if(cdev_add(&cdev->cdev, cdev->cdevno, 1) < 0)
{
printk("cdev_add failed\n");
goto unregister_region;
}
/*在/sys/class下创建一个新的文件夹,名字叫my_dev,也可以说创建一个逻辑类*/
cdev->class = class_create(THIS_MODULE, "my_dev");
if(IS_ERR(cdev->class))
{
return -1;
}
if(cdev->class)
{
/*类生成之后,在/dev创建一个新的设备节点*/
cdev->sys_device = device_create(cdev->class, NULL, cdev->cdevno, NULL ,"cdev");
}
return 0;
unregister_region:
unregister_chrdev_region(dev, 255);
return -1;
}
int my_cdev_exit(void)
{
struct my_cdev *dev = &g_my_cdev;
if(NULL == cdev->sys_device)
{
return 0;
}
if(cdev->sys_device)
{
device_destory(cdev->class, cdev->cdevno);
cdev->sys_device = NULL;
}
if(cdev->class)
{
class_destroy(cdev->class);
}
cdev_del(&cdev->cdev);
if(cdev->major)
{
unregister_chrdev_region(MKDEV(cdev->major,0), 255);
}
return 0;
}
static int __init mod_init(void)
{
int ret = 0;
/*初始化控制部分*/
my_cdev_init();
return pci_register_driver(&pci_driver);/*struct pci_driver pci_driver*/
}
static void __exit mod_exit(void)
{
pci_unregister_driver(&pci_driver);
my_cdev_exit();
}
module_init(mod_init);
module_exit(mod_exit);
注意alloc_chrdev_region()中的名字要和class_create()中名字一致,否则rmmod时候会kill掉,device_destory()会报错