linux字符设备驱动架构,linux驱动开发--字符设备:cdd_cdev结构中private_data使用
本站寻求有缘人接手,详细了解请联系站长QQ1493399855
private_data改进
为设备驱动支持多个设备个体做准备,针对private_data进行改进
在设备打开操作中通过inode中保存的i_cdev获取代表当前设备的cdev对象
通过代表当前设备的cdev对象得到包含该对象的设备私有数据结构体
将设备私有数据结构体指针保存到struct file的private_data成员中
在其它设备操作中直接使用保存在struct file的private_date成员中的当前设备私有数据结构体
//Copyright (c) 2013.TianYuan
//All rights reserved.
//
//文件名称: char_device_driver06.c
//文件标识:
支持多设备:创建10个设备节点文件,通过cdd_cdev结构中的led变量区分是哪个节点
//#测试: cat /dev/cdd0
//当前版本:1.0
//作者:wuyq
//取代版本:xxx
//原作者:xxx
//完成日期:2013-11-28
#include "linux/init.h"
#include "linux/module.h"
#include "linux/fs.h"
#include "linux/cdev.h"
#include "linux/device.h"
#include "linux/slab.h"
MODULE_LICENSE("GPL");
#define CDD_MAJOR 200//cat
/proc/devices找一个尚未使用的
#define CDD_MINOR 0
#define CDD_COUNT 10
dev_t dev = 0;
u32 cdd_major = 0;
u32 cdd_minor = 0;
struct class *dev_class = NULL;
struct cdd_cdev{
struct cdev cdev;
struct device *dev_device;
u8 led;
};
struct cdd_cdev *cdd_cdevp = NULL;
int cdd_open(struct inode* inode, struct file
*filp)
{
struct cdd_cdev *pcdevp = NULL;
printk("enter cdd_open! ");
pcdevp = container_of(inode->i_cdev,
struct cdd_cdev, cdev);
printk("led = %d ",
pcdevp->led);
filp->private_data = pcdevp;
return 0;
}
int cdd_read(struct file *filp, char __user
*buf, size_t count, loff_t *offset)
struct cdd_cdev *cdevp =
filp->private_data;
printk("enter cdd_read! ");
cdevp->led);
int cdd_write(struct file *filp, const char
__user *buf, size_t count, loff_t *offset)
printk("enter cdd_write! ");
int cdd_ioctl(struct inode *inode, struct
file *filp, unsigned int cmd, unsigned long data)
printk("enter cdd_ioctl! ");
int cdd_release(struct inode *inode, struct
file *filp)
printk("enter cdd_release! ");
struct file_operations cdd_fops =
.owner = THIS_MODULE,
.open = cdd_open,
.read = cdd_read,
.write = cdd_write,
.ioctl = cdd_ioctl,
.release = cdd_release,
int __init cdd_init(void)
int ret = 0;
int i = 0;
if(cdd_major){
dev = MKDEV(CDD_MAJOR,
CDD_MINOR);//生成设备号
//注册设备号;1、要注册的起始设备号2、连续注册的设备号个数3、名字
ret = register_chrdev_region(dev, CDD_COUNT,
"cdd_demo");
}else{
// 动态分配设备号
ret = alloc_chrdev_region(&dev,
cdd_minor, CDD_COUNT, "cdd_demo02");
if(ret < 0){
printk("register_chrdev_region
failed! ");
goto failure_register_chrdev;
//获取主设备号
cdd_major = MAJOR(dev);
printk("cdd_major = %d ",
cdd_major);
cdd_cdevp = kzalloc(sizeof(struct
cdd_cdev)*CDD_COUNT, GFP_KERNEL);
if(IS_ERR(cdd_cdevp)){
printk("kzalloc failed! ");
goto failure_kzalloc;
//创建设备类
dev_class = class_create(THIS_MODULE,
"cdd_class");
if(IS_ERR(dev_class)){
printk("class_create failed! ");
goto failure_dev_class;
for(i=0; i
//初始化cdev
cdev_init(&(cdd_cdevp[i].cdev),
&cdd_fops);
//添加cdev到内核
cdev_add(&(cdd_cdevp[i].cdev), dev+i,
1);
// “/dev/xxx”
device_create(dev_class, NULL, dev+i, NULL,
"cdd%d", i);
cdd_cdevp[i].led =
i;//为led变量赋值,通过led区分是一组设备中的哪个设备
failure_dev_class:
kfree(cdd_cdevp);
failure_kzalloc:
unregister_chrdev_region(dev,
CDD_COUNT);
failure_register_chrdev:
return ret;
void __exit cdd_exit(void)
//逆序消除
for(; i < CDD_COUNT; i++){
device_destroy(dev_class, dev+i);
cdev_del(&(cdd_cdevp[i].cdev));
//cdev_del(&((cdd_cdevp+i)->cdev));
class_destroy(dev_class);
module_init(cdd_init);
module_exit(cdd_exit);