IMX257 linux设备驱动之Cdev结构

发布者:Meilin8888最新更新时间:2024-08-15 来源: cnblogs关键字:linux设备驱动 手机看文章 扫描二维码
随时随地手机看文章

一、CDEV结构

  1. /*  

  2. *内核源码位置  

  3. *linux2.6.38/include/linux/cdev.h  

  4. */  

  5.     

  6. struct cdev {  

  7.     struct kobject kobj;  

  8.     struct module *owner;   //一般初始化为:THIS_MODULE  

  9.     const struct file_operations *ops;   

  10. //字符设备用到的例外一个重要的结构体file_operations,cdev初始化时与之绑定  

  11.     struct list_head list;  

  12.     dev_t dev;  //主设备号24位 与次设备号8位,dev_t为32位整形  

  13.     unsigned int count;  

  14. };

 

二、file_operation 结构

  1. /* 

  2. ~/include/linux/fs.h 

  3. */  

  4.     

  5. struct file_operations {  

  6.     struct module *owner;  

  7.     loff_t (*llseek) (struct file *, loff_t, int);  

  8.     ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);  

  9.     ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);  

  10.     ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);  

  11.     ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);  

  12.     int (*readdir) (struct file *, void *, filldir_t);  

  13.     unsigned int (*poll) (struct file *, struct poll_table_struct *);  

  14.     long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);  

  15.     long (*compat_ioctl) (struct file *, unsigned int, unsigned long);  

  16.     int (*mmap) (struct file *, struct vm_area_struct *);  

  17.     int (*open) (struct inode *, struct file *);  

  18.     int (*flush) (struct file *, fl_owner_t id);  

  19.     int (*release) (struct inode *, struct file *);  

  20.     int (*fsync) (struct file *, int datasync);  

  21.     int (*aio_fsync) (struct kiocb *, int datasync);  

  22.     int (*fasync) (int, struct file *, int);  

  23.     int (*lock) (struct file *, int, struct file_lock *);  

  24.     ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);  

  25.     unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);  

  26.     int (*check_flags)(int);  

  27.     int (*flock) (struct file *, int, struct file_lock *);  

  28.     ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);  

  29.     ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);  

  30.     int (*setlease)(struct file *, long, struct file_lock **);  

  31.     long (*fallocate)(struct file *file, int mode, loff_t offset,  

  32.               loff_t len);  

  33. };  

 

三、为cdev申请内存

接下来,我们就需要为cdev申请内存,然后再通过cdev_init 函数将cdev与file_operation结构体联系起来,

  1. void cdev_init(struct cdev *cdev, const struct file_operations *fops)  

  2. {  

  3.     memset(cdev, 0, sizeof *cdev);  

  4.     INIT_LIST_HEAD(&cdev->list);  

  5.     kobject_init(&cdev->kobj, &ktype_cdev_default);  

  6.     cdev->ops = fops;  

  7. }  

 

最后通过cdev_add函数,将cdev添加到内核中

  1. int cdev_add(struct cdev *p, dev_t dev, unsigned count)  

  2. {  

  3.     p->dev = dev;  

  4.     p->count = count;  

  5.     return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);  

  6. }  

 

四、实例解析

1.自定义一个cdev结构体

如图所示,上述代码中,先自定义一个简单的cdev结构体key_dev,然后再实例化key_device, 接下来就定义一个我们接下来要操作的数组key_buff[MEM_SIZE],MEM_SIZE为自定义的内存的大小。

 

2.在init函数中初始化cdev结构体

当我们的应用程序调用open函数打开设备时,

在init函数中初始化cdev结构体,为cdev结构体开辟内存,连接cdev与fops结构体,注册cdev进入内核

 

3.一旦注册入内核,我们就可以开始使用了

当我们的应用程序打开设备时,在open函数中将filp的private_data赋值为我们所分配的key_device的结构体

 

4.释放cdev内存

当我们不用驱动时自然就要释放我们刚刚开辟的内存。

如图所示,首先删除cdev结构体,然后再使用kfree来释放cdev释放申请的内存

 

5.编译与测试

 

 

如图所示,我们在应用程序中先使用write函数往数组中写入'hello,Lover雪儿'的字符串,然后再使用read函数读取内容,但是,必须注意一点,在每次read后者write前,必须先使用lseek函数中重定位指针。

附上驱动程序源代码:

  1 #include

  2 #include

  3 #include

  4 #include

  5 #include

  6 #include

  7 #include

  8 #include

  9 #include

 10 #include

 11 #include

 12 #include

 13 

 14 #define DEVICE_NAME    'cdev'

 15 #define Driver_NAME 'key_cdev'

 16 

 17 #define KEY_MAJOR 220

 18 #define KEY_MINOR 0

 19 #define COMMAND1 1

 20 #define COMMAND2 2

 21 #define MEM_SIZE 256

 22 

 23 struct key_dev {

 24         struct cdev cdev;

 25 };

 26 struct key_dev *key_device;

 27 static unsigned char key_buff[MEM_SIZE];

 28 

 29 //auto to create device node

 30 static struct class *drv_class = NULL;

 31 static struct class_device *drv_class_dev = NULL;

 32 

 33 static int key_open(struct inode *inode,struct file *filp){

 34     filp->private_data = key_device;

 35     return 0;

 36 }

 37 

 38 static int key_release(struct inode* inode,struct file *filp){

 39     return 0;

 40 }

 41 

 42 static ssize_t key_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos){

 43     ssize_t ret = 0;

 44     loff_t pos = *f_pos;

 45     if(pos > MEM_SIZE)    //如果文件指针偏移超出文件大小

 46         return ret = 0;

 47     if(count > (MEM_SIZE - pos))

 48         count = 256 - pos;    //若内存不足,则写到内存满的位置

 49     pos += count;

 50     //读出数据

 51     if(copy_to_user(buf,key_buff + *f_pos,count)){

 52         return ret = -EFAULT;

 53     }

 54     *f_pos = pos;

 55     return count;

 56 }

 57 

 58 static ssize_t key_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos){

 59     ssize_t ret = -ENOMEM;

 60     loff_t pos = *f_pos;        //获取当前文件指针偏移

 61     if(pos > MEM_SIZE)    //如果文件指针偏移超出文件大小

 62         return ret;

 63     if(count > (MEM_SIZE - pos))

 64         count = 256 - pos;    //若内存不足,则写到内存满的位置

 65     pos += count;

 66     //从fops处开始写入数据

 67     if(copy_from_user(key_buff + *f_pos,buf,count)){

 68         ret = -EFAULT;

 69         return ret;

 70     }

 71     *f_pos = pos;

 72     return count;

 73 }

 74 

 75 static int key_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){

 76     switch(cmd){

 77         case COMMAND1: printk('<0>ncommand 1 n'); break;

 78         case COMMAND2: printk('<0>ncommand 2 n'); break;

 79         default: printk('<0>command default n'); break;

 80     }

 81     return 0;

 82 }

 83 

 84 static loff_t key_llseek(struct file *filp, loff_t off, int whence){

 85     loff_t pos;

 86     pos = filp->f_pos;    //获取文件指针当前位置

 87     switch(whence){

 88         case 0: pos = off;    break;    //重定位到文件开头

[1] [2]
关键字:linux设备驱动 引用地址:IMX257 linux设备驱动之Cdev结构

上一篇:IMX257 Linux内存空间内存分配
下一篇:【改进定时器】IMX257实现GPIO-IRQ定时器消抖驱动程序

推荐阅读最新更新时间:2026-03-24 10:48

Linux设备驱动开发 - 字符设备驱动
struct cdev结构体: 1 struct cdev { 2 struct kobject kobj; /* 内嵌的kobject对象 */ 3 struct module *owner; /* 所属模块 */ 4 const struct file_operations *ops; /* 文件操作结构体 */ 5 struct list_head list; 6 dev_t dev; /* 设备号 */ 7 unsigned int count; 8 }; struct file_operations原形: 1 struct file_operations { 2 struct mod
[单片机]
<font color='red'>Linux</font><font color='red'>设备驱动</font>开发 - 字符<font color='red'>设备驱动</font>
Linux设备驱动开发 - 平台设备驱动
Linux2.6的内核中引入了一种新的设备驱动模型-平台(platform)设备驱动,平台设备驱动分为平台设备(platform_device)和平台驱动(platform_driver),平台设备的引入使得Linux设备驱动更加便于移植。 一、平台设备 平台设备结构体: 1 struct platform_device { 2 const char * name; /* 设备名 */ 3 int id; 4 struct device dev; /* 设备结构体 */ 5 u32 num_resources; /* 设备资源
[单片机]
Linux平台设备驱动 - 按键设备驱动
之前的一篇博客简单介绍了平台设备驱动模型(http://www.cnblogs.com/ape-ming/p/5107641.html),现在就根据那篇博客所列出来的模板把上一篇博客(http://www.cnblogs.com/ape-ming/p/5110996.html)的例程改成平台设备驱动模型。 一、平台设备 根据模板首先要写一个平台设备加载函数: 1 /* 2 * 函数名 : button_device_init 3 * 函数功能: 设备加载 4 */ 5 6 static int __init button_device_init(void) 7 { 8 int ret = 0;
[单片机]
ARM Linux字符设备驱动程序
1、主设备号和次设备号(二者一起为设备号): 一个字符设备或块设备都有一个主设备号和一个次设备号。主设备号用来标识与设备文件相连的驱动程序,用来反 映设备类型。次设备号被驱动程序用来辨别操作的是哪个设备,用来区分同类型的设备。 linux内核中,设备号用dev_t来描述,2.6.28中定义如下: typedef u_long dev_t; 在32位机中是4个字节,高12位表示主设备号,低12位表示次设备号。 可以使用下列宏从dev_t中获得主次设备号:                    也可以使用下列宏通过主次设备号生成dev_t: MAJOR(dev_t dev); MKDEV(int major,int
[单片机]
ARM <font color='red'>Linux</font>字符<font color='red'>设备驱动</font>程序
linux设备驱动之USB数据传输分析 一
三:传输过程的实现 说到传输过程,我们必须要从URB开始说起,这个结构的就好比是网络子系统中的skb,好比是I/O中的bio.USB系统的信息传输就是打成URB结构,然后再过行传送的. URB的全称叫USB request block.下面从它的接口说起. 3.1:URB的相关接口 1:URB的创建 URB的创建是由usb_alloc_urb()完成的.这个函数会完成URB内存的分配和基本成员的初始化工作.代码如下: struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags) { struct urb *urb; urb = kmalloc(sizeof(struc
[单片机]
S3C2440驱动篇—Linux平台设备驱动
在设备驱动程序中经常会见到和platform相关的字段,分布在驱动程序的多个角落,这也是2.6内核中比较重要的一种机制,把它原理弄懂,对以后分析驱动程序很有帮助:在linux2.6设备模型中,关心总线,设备,驱动这三个实体,总线将设备和驱动绑定,在系统每注册一个设备的时候,会寻找与之匹配的驱动。相反,在系统每注册一个驱动的时候,寻找与之匹配的设备,匹配是由总线来完成的。 一个现实的Linux 设备和驱动通常都需要挂接在一种总线上,对于本身依附于PCI、USB、I2C、SPI 等的设备而言,这自然不是问题,但是在嵌入式系统里面,SoC 系统中集成的独立的外设控制器、挂接在SoC 内存空间的外设等确不依附于此类总线。基于这一背景,Li
[单片机]
linux中LCD设备驱动(3)——基于s3c6410平台
上一篇在说LCD设备驱动对应的probe函数时,没有说完,这一篇接着继续说probe函数。 s3cfb_pre_init();上一次说到了这个函数,而且还讲到了一个结构体s3cfb_fimd_info_t,并说了它的大致作用。 s3cfb_set_backlight_power(1);看名字就只到它的大致作用,与背光灯有关,源码如下: static void s3cfb_set_backlight_power(int to) { s3cfb_fimd.backlight_power = to; if (s3cfb_fimd.set_backlight_power) (s3cfb_fimd.set_backlight_
[单片机]
linux中LCD设备驱动(4)——基于s3c6410平台
我们这一篇来说与具体的TFT显示器有关的部分,当遇到具体的显示器是我们应该设置什么参数,怎样设置这些参数。 1、在s3cfb_WXCAT43.c (linux2.6.28driversvideosamsung)文件中是有关具体显示器的设置。我们一段一段来看。 #include linux/wait.h #include linux/fb.h #include linux/delay.h #include linux/platform_device.h #include plat/regs-gpio.h #include plat/regs-lcd.h #include s3cfb.h #define S3C
[单片机]
<font color='red'>linux</font>中LCD<font color='red'>设备驱动</font>(4)——基于s3c6410平台
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved