前面我们学习了杂项设备驱动模型、早期经典字符设备驱动模型,这一小节来讲解Linux中的标准字符设备驱动。

目录

  • (一)为什么引入标准字符设备驱动模型
  • (二)相关接口
  • (三)注册流程
  • (四)程序示例

(一)为什么引入标准字符设备驱动模型

前面讲解了杂项设备驱动模型和早期经典设备驱动模型,但是他们都存在不足之处

杂项设备存在的不足: 主设备号固定为10,最多设备为0-255个次设备号,设备号有限
早期经典驱动模型不足: 早期经典的字符设备主设备号为0-255除10外,但是申请一次主设备号,该设备号下的所有次设备号(0-255)均属于同一设备,且不会在申请同时创建节点文件,需要手动创建
出于以上的不足之处,内核中对驱动模型进行了升级,引入了标准字符设备驱动模型
标准字符设备驱动模型: 标准字符设备驱动模型中对设备号进行了数据的规定,规定设备号为一个32位的无符号整型数据

(二)相关接口

(1)int cdev_add(struct cdev *p, dev_t dev, unsigned count)这个函数是添加到字符设备系统中,注册标准字符设备驱动。

int cdev_add(struct cdev *p, dev_t dev, unsigned count)
{p->dev = dev;p->count = count;return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
}//第一个参数结构体原型
struct cdev {struct kobject kobj;   //不关心struct module *owner;  //一般赋值为THIS_MODULEconst struct file_operations *ops;     //文件操作结构体struct list_head list;     //dev_t dev;           //设备号unsigned int count;   //表示申请设备号的数量
};

(2)struct cdev 结构体可以手动静态初始化,但是我们通常使用动态申请,本篇文章主要介绍动态相关的函数。

struct cdev *cdev_alloc(void);//动态申请struct cdev结构体 的内存void cdev_init(struct cdev *, const struct file_operations *);//初始化struct cdev结构体

(3)删除标准字符设备接口


void cdev_del(struct cdev *);

(4)设备号合成相关的接口

1.自己指定主次设备号,通过MKDEV合成dev_t dev=MKDEV(major,minor);2.静态申请int register_chrdev_region(dev_t from, unsigned count, const char *name)3.动态申请
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name)
{struct char_device_struct *cd;cd = __register_chrdev_region(0, baseminor, count, name);if (IS_ERR(cd))return PTR_ERR(cd);*dev = MKDEV(cd->major, cd->baseminor);return 0;
}

(5)创建设备节点 device_create

struct device *device_create(struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...)
{va_list vargs;struct device *dev;va_start(vargs, fmt);dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);va_end(vargs);return dev;
}

(6)设备类struct class 创建

#define class_create(owner, name)        \
({                      \static struct lock_class_key __key;    \__class_create(owner, name, &__key);   \
})

(7)标准字符设备驱动注销cdev_del

void cdev_del(struct cdev *p)
{cdev_unmap(p->dev, p->count);kobject_put(&p->kobj);
}

(8)注销设备号unregister_chrdev_region()

void unregister_chrdev_region(dev_t from, unsigned count)
{dev_t to = from + count;dev_t n, next;for (n = from; n < to; n = next) {next = MKDEV(MAJOR(n)+1, 0);if (next > to)next = to;kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));}
}

(9)销毁设备类:

void class_destroy(struct class *cls)
{if ((cls == NULL) || (IS_ERR(cls)))return;class_unregister(cls);
}

(10)销毁设备节点: device_destroy(struct class *class, dev_t devt)

void device_destroy(struct class *class, dev_t devt)
{struct device *dev;dev = class_find_device(class, NULL, &devt, __match_devt);if (dev) {put_device(dev);device_unregister(dev);}
}

(11)释放cdev空间:

static inline void kfree(void *p)
{free(p);
}

(三)注册流程

(1)定义struct cdev 结构体指针

 struct cdev *cdev =NULL

(2)申请cdev结构体空间并初始化

cdev = cdev_alloc();//动态申请空间
cdev_init(cdev,&fop);//fop为struct file_operations类型的结构体

(3)申请设备号–动态

dev_t dev=0;
int ret =alloc_chrdev_region(&dev,0, CDEVCOUNT, CDEVNAME);

(4)将字符设备添加到系统

 ret =cdev_add(cdev,dev, CDEVCOUNT);

(5)创建设备类

 struct class * cdevclass =NULL;//定义设备节点类接构体cdevclass = class_create(THIS_MODULE, INODENAME)

(6)添加设备节点

reate(cdevclass, NULL, dev, NULL, "mydevice",);

(四)程序示例

chrdev.c

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/slab.h>#define CDEVCOUNT 5
#define CDEVNAME "cdevdevice"
#define INODENAME "mycdev"
int i=0;
dev_t dev=0;
struct cdev * cdev =NULL;
struct class * cdevclass =NULL;int cdev_open (struct inode *node, struct file *file)
{printk("cdev_open is install\n");return 0;
}
ssize_t cdev_read (struct file *fp, char __user *buf, size_t size, loff_t *offset)
{printk("cdev_read is install\n");return 0;
}
ssize_t cdev_write (struct file *fp, const char __user * buf, size_t size, loff_t *offset)
{printk("cdev_write is install\n");return 0;
}
int cdev_release (struct inode *node, struct file *fp)
{printk("cdev_release is install\n");return 0;
}
struct file_operations fop={.open=cdev_open,.read=cdev_read,.write=cdev_write,.release=cdev_release,
};void mycdev_add()
{//1.申请设备号--动态int ret =alloc_chrdev_region(&dev,0, CDEVCOUNT, CDEVNAME);if(ret)return ;//初始化cdev结构体cdev = cdev_alloc();if(!cdev){goto out;   }cdev_init(cdev,&fop);//添加字符设备到系统中ret =cdev_add(cdev,dev, CDEVCOUNT);if(ret){goto out1;}//创建设备类cdevclass = class_create(THIS_MODULE, INODENAME);if(IS_ERR(cdevclass)){goto out2;}
for (i=0;i<CDEVCOUNT;i++)device_create(cdevclass, NULL, dev+i, NULL, "mydevice%d",i);out:unregister_chrdev_region(dev,CDEVCOUNT);  return ;out1:unregister_chrdev_region(dev,CDEVCOUNT);kfree(cdev);return ;
out2:cdev_del(cdev);unregister_chrdev_region(dev,CDEVCOUNT);kfree(cdev);return ;
}static int __init  dev_module_init(void)
{mycdev_add();printk("this is dev_module_init \n");return 0;
}static void __exit dev_module_cleanup(void)
{device_destroy(cdevclass, dev);class_destroy(cdevclass);cdev_del(cdev);unregister_chrdev_region(dev, CDEVCOUNT);kfree(cdev);printk("this is dev_module_cleanup\n");
}module_init(dev_module_init);
module_exit(dev_module_cleanup);
MODULE_LICENSE("GPL");

Makefile

CFLAG =-C
TARGET = chrdev
TARGET1 = chr_app
KERNEL = /mydriver/linux-3.5
obj-m += $(TARGET).oall:make $(CFLAG)  $(KERNEL) M=$(PWD)arm-linux-gcc -o $(TARGET1) $(TARGET1).c
clean:make $(CFLAG)  $(KERNEL) M=$(PWD) clean

chr_app.c

#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main(int argc, char *argv[])
{int fd= open(argv[1],O_RDWR);if(fd== -1){perror("open");return -1;}write(fd,"hell",4);close(fd);return 0;
}

关于上面的驱动程序都是建立在前面的模块化编程的基础上编写的,不懂的往前看前面的博客就行了,演示一下效果


本文章仅供学习交流用禁止用作商业用途,文中内容来水枂编辑,如需转载请告知,谢谢合作

微信公众号:zhjj0729

微博:文艺to青年

(六)Linux之设备驱动模型(续)相关推荐

  1. linux设备模型 字符设备,Linux 字符设备驱动模型之框架解说

    一.软件操作硬件设备模型 在进行嵌入式开发的过程中,在常做的事情就是驱动配置硬件设 备,然后根据功能需求使用硬件设备,实现功能的逻辑.如下图为其 相互之间的关系. 如上图所示: 驱动程序:主要作为操作 ...

  2. LINUX I2C设备驱动模型分析之二 总线部分分析

    上一章我们对I2C模块做了总体框架的分析,本章我们主要分析下I2C模块的总线部分,主要涉 及总线初始化.总线相关属性.总线相关接口函数处理等几部分 I2c bus的定义 I2c bus的定义如下,主要 ...

  3. (五)Linux之设备驱动模型

    目录 (一)Linux内核驱动简介 (二)杂项设备驱动模型 (1)相关接口 (2)杂项设备注册过程 (三)早期经典字符设备驱动模型 (1)相关接口 (2)杂项设备注册过程 (二)杂项和早期经典的区别 ...

  4. linux平台设备驱动模型是什么意思,Linux设备驱动模型之我理解

    点击(此处)折叠或打开 /* my_bus.c   */ #include #include #include #include #include #include "my_bus.h&qu ...

  5. linux字符设备文件的打开操作,Linux字符设备驱动模型之字符设备初始化

    因为Linux字符设备驱动主要依赖于struct cdev结构,原型为: 所以我们需要对所使用到的结构成员进行配置,驱动开发所使用到的结构成员分别为:[unsigned int count;].[de ...

  6. LINUX SPI设备驱动模型分析之二 SPI总线模块分析

    上一篇文章我们简要介绍了SPI驱动模块,本章我们详细说明一下spi总线.设备.驱动模块的注册.注销以及这几个模块之间的关联. SPI总线的注册 spi模块也是基于LINUX设备-总线-驱动模型进行开发 ...

  7. Linux字符设备驱动模型

    版本 颁布日期 修订章节 0.1 2015.08.13 撰写草稿 0.2 2015.12.07 整合字符型设备驱动 0.3 2015.12.07 整理文档,尚未验证驱动源码 0.4 2016.02.2 ...

  8. linux设备驱动模型-linux驱动开发第5部分-朱有鹏-专题视频课程

    linux设备驱动模型-linux驱动开发第5部分-4285人已学习 课程介绍         本课程是linux驱动开发的第5个课程,主要内容是linux的设备驱动模型,包括总线.类.设备.驱动等概 ...

  9. Linux Platform平台设备驱动模型

    Linux总线设备驱动模型主要包含总线.设备.驱动三个部分. 现实总线:一个现实的Linux设备和驱动通常都需要挂接在一种总线上,对于本身依附于PCI.USB.I2C.SPI等的设备而言,这自然不是问 ...

最新文章

  1. iOS边练边学--CALayer,非根层隐式动画,钟表练习
  2. 水晶报表-横向设计页面,设置网格高度
  3. SQL Server2012 安装方法
  4. Java中的HashMap和Hashtable有什么区别?
  5. 宝洁侮辱女性?其公众号发文 “女人脚臭是男人的5倍”,官方回应了...
  6. java与jsp的关系_浅谈servlet与jsp的关系
  7. Item08. 多级指针(Pointers to Pointers)
  8. 北航计算机组成原理课程设计-2021秋 PreProject-MIPS-入门简介
  9. 计算机已被锁定请联系管理员,win7电脑开机收到提示“您的账户已被停用,请向系统管理员咨询”怎么办?...
  10. ASP.NET删除服务器端文件,asp.net删除服务器上的文件
  11. 论文笔记—RGB-D SLAM in Dynamic Environments Using Static Point Weighting
  12. 全国大学生英语竞赛总结
  13. python数据分析师前景及待遇怎么样_数据分析师未来五年发展前景怎么样?
  14. 高德地图api的使用
  15. 经典利用永恒之蓝漏洞对Windows操作系统进行攻击
  16. 以匠心守初心!百望云荣膺人民网“第十九届人民匠心飞跃奖”
  17. 【机器学习】使用Matlab和CNN完成回归任务
  18. ireport4.5在JVM中添加新字体解决方案(Font ‘標楷體‘ is not available to the JVM. See the Javadoc for more details.)
  19. 用计算机代码选址的优点,计算机机房选址原则
  20. 计算机硬件的最低配置,Windows7系统的最低硬件配置要求是什么

热门文章

  1. deepin linux 2014 硬盘安装教程,Linux Deepin的硬盘安装
  2. Elasticsearch7.15.2 mysql8.0.26 logstash-input-jdbc 数据增量索引构建
  3. RuoYi-Cloud 部署篇_01(linux环境 mysql+nginx版本)
  4. Centos7 安装docker-compose
  5. 正则表达式简单语法及常用正则表达式
  6. 第11篇:Flowable-BPMN部署常见问题没有对ACT_RE_PROCDEF表进行插入操作
  7. tomcat9控制台中文乱码
  8. cmd下pip安装mysql_Windows下使用pip安装mysql-python
  9. python中idle怎么打开_为什么我的python脚本只打开IDLE?
  10. java hashmap读,java – ConcurrentHashmap – 读取和删除