前面关于设备号、设备节点、class类和device设备都是用全局变量定义的,多了以后难免杂乱。
所以可以创建一个设备结构体,把设备号、设备节点、class类和device设备都放进去。
struct device_test{
dev_t dev_num;
static int major = 0;
static int minor = 0;
struct cdev cdev_test;
struct class *class;
struct device *device;
char kbuf[];
};
/* 然后定义结构体变量 */
struct device_test dev1;
【问】为什么这么做??
可移植性更高
【问】以下操作是为了什么?
static int cdev_open(struct inode *inode, struct file *filp)
{
file->private_data = &dev1; //指向设备结构体
......
}
static ssize_t cdev_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
struct device_test *test_dev = (struct device_test *)file->private_data;
.....
}
面向对象
【使用文件私有数据完善驱动模板】
struct device_test{
dev_t dev_num;
static int major = 0;
static int minor = 0;
struct cdev cdev_test;
struct class *class;
struct device *device;
char kbuf[32] = "this is cdev_read!"; //模拟内核寄存器的数据
};
/* 然后定义结构体变量 */
struct device_test dev1;
struct file_operations cdev_file_operations = {
.owner = THIS_MODULE;
.open = cdev_open;
.read = cdev_read;
.write = cdev_write;
.release = cdev_release;
}
static int moduleparam_init()
{
int ret;
/* 动态申请 */
ret = alloc_chrdev_region(&dev1.dev_num,0,1,"HELLO");
//动态注册设备号成功,则打印
if(ret<0){
printk("alloc_chrdev_region error!\n");
}
printk("alloc_chrdev_region ok\n");
dev1.major_num =MAJOR(dev1.dev_num); //将主设备号取出来
dev1.minor_num = MINOR(dev1.dev_num);//将次设备号取出来
printk("major_num = %d\n", dev1.major_num);//打印传入进来的主设备号
printk("minor_num = %d\n", dev1.minor_num);//打印传入进来的次设备号
dev1.cdev_test.owner = THIS_MODULE;
cdev_init(dev1.cdev_test, &cdev_file_operations);
cdev_add(&dev1.cdev_test, dev1.dev_num, 1);
class = class_creat(THIS_MODULE, "test");
device = device_creat( dev1.class,NULL, dev1.dev_num,,NULL,"test")
return 0;
}
static int cdev_open(struct inode *inode, struct file *filp)
{
/*****************************************/
file->private_data = &dev1; //指向设备结构体
return 0;
}
static ssize_t cdev_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
/*****************************************/
struct device_test *test_dev = (struct device_test *)file->private_data;
/* 把这个数组的数据拷贝到寄存器中 */
if(copy_to_user(buf, test_dev->kbuf, strlen(test_dev->kbuf))!= 0);
{
printk("copy_to_user error !\n");
return -1;
}
printk("cdev_read success\n");
return 0;
}
static ssize_t cdev_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{
/*****************************************/
struct device_test *test_dev = (struct device_test *)file->private_data;
test_dev->kbuf = {0};
if(copy_from_user( test_dev->kbuf, buf ,sizeof(buf))!= 0);
{
printk("copy_from_user error !\n");
return -1;
}
printk("cdev_write success\n");
return 0;
}
static int cdev_release(struct inode *inode, struct file *filp)
{
/*****************************************/
file->private_data = &dev1; //指向设备结构体
return 0;
}
static void hello_exit(void)
{
unregister_chrdev_region( dev1.dev_num,DEVICE_NUMBER);//注销设备号
cdev_del(& dev1.cdev_test); //销毁字符设备
device_destroy( dev1.class, dev1.dev_num);
class_destroy( dev1.class);
printk("gooodbye! \n");
}