因为Linux字符设备驱动主要依赖于struct cdev结构,原型为:

所以我们需要对所使用到的结构成员进行配置,驱动开发所使用到的结构成员分别为:【unsigned int count;】、【dev_t dev;】、【const struct file_operations *ops;】。

开发流程如下图:

一、字符设备驱动初始化

1、分配设备cdev

Cdev变量的定义可以采用静态和动态两种方法进行分配。静态方法直接分配内存,而动态方法随机分配内存。

静态分配cdev:

定义:struct cdev mdev;

mdev即代表相应的字符设备空间地址。

动态分配cdev:

定义:struct cdev *pdev = cdev_alloc();

pdev即代表对于的字符设备的空间地址。

2、初始化设备cdev

Linux内核中,字符设备struct cdev的初始化使用cdev_init。其原型如下:

参数:

cdev:待初始化的struct cdev结构

fops:设备对应的操作函数集

由原型所要求的参数可知,需要初始化一个字符设备,必须根据申请一个struct cdev结构的空间,然后对其成员进行配置。即实现设备的操作函数集、为设备申请设备号(包括主设备号和次设备号)、指定此类型的字符设备有多少个相同设备。

3、注册设备cdev

Linux内核中字符设备的注册使用cdev_add函数来进行完成注册。其原型如下:

其相关参数定义为:

p:待添加到内核中的字符设备结构,即为struct cdev。

dev:设备号

count:该类设备的设备数量,各个设备的区别体现为从设备号。

在开发驱动时,当确定了字符设备的结构,主设备号和从设备号、设备的数量,就可以使用cdev_add函数将相应的字符设备添加到Linux内核驱动中进行注册。

4、硬件初始化

关于硬件的初始化就简单了。直接根据所需要操作的字符设备,阅读器Datasheet,然后根据Datasheet进行硬件的配置即可。

二、设备操作和驱动操作映射

从上图基本可知,在用户空间的每一种硬件设备操作函数,在内核空间通用有一个映射操作函数实现。

•int (*open) (struct inode *, struct file *):打开设备,响应open系统

•int (*release) (struct inode *, struct file *):关闭设备,响应close系统调用

•loff_t (*llseek) (struct file *, loff_t, int):重定位读写指针,响应lseek系统调用

•ssize_t (*read) (struct file *, char __user *, size_t, loff_t *):从设备读取数据,响应read系统调用

•ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *):向设备写入数据,响应write系统调用

从以上函数指针操作方法中可以提取出两个重要的参数成员,即为struct file和struct inode。

【struct file】:在Linux系统中,每一个打开的文件,在内核中都会对应的关联一个struct file结构体,它由内核在打开文件时创建,在文件关闭后释放。

其非常重要的成员有:

loff_t f_pos /*文件读写指针*/

struct file_operations *f_op /*该文件所对应的操作*/

【struct inode】:每一个存在于文件系统里面的文件都会关联一个inode 结构,该结构主要用来记录文件物理上的信息。因此, 它和代表打开文件的file结构是不同的。一个文件没有被打开时不会关联file结构,但是却会关联一个inode 结构。

在struct inode结构中,dev_t i_rdev尤其重要,表示设备号。

三、struct file_operations结构常用设备操作解析

1.open设备操作

根据原型可知,open设备函数方法是在进行开始启用操作设备时的初始化工作,与用户空间的open函数对应,通常情况下,open函数实现:

(1)表明次设备号

(2)启用设备

当然,如果在启用设备时,不需要任何的准备操作或者初始化操作,那么open函数可以为空函数,不实现。

2.release设备操作

release函数方法的作用正好和open函数方法的作用相反,它在设备关闭时用到,与用户空间的close对应。通常用来进行关闭设备的实现。如果所操作的设备在关闭时不需要其他操作,那么使其为空函数即可。

3.read设备操作

read方法主要完成两件事:

(1)访问硬件操作,从设备中读取数据。

(2)将从设备端读取到的数据返回给用户空间的应用程序read函数。

其read方法的具体原型可分析如下:

ssize_t (*read) (struct file *filp, char __user *buff, size_t count, loff_t *offp)

参数分析:

filp:与字符设备文件关联的file结构指针, 由内核创建。

buff : 从设备读取到的数据,需要保存到的位置。由read系统调用提供该参数。

count: 请求传输的数据量,由read系统调用提供该参数。

offp: 文件的读写位置,由内核从file结构中取出后,传递进来。

那么实际上在这里就存在了一个问题,从内核空间如何将数据返回给用户空间???

在Linux内核中,为从内核空间将数据返回到用户空间提供了函数方法,即为:copy_to_user。其原型如下:

之所以采用copy_to_user函数的原因是,buff参数来源于用户空间的指针,这类指针在内核空间中不能直接被内核代码直接引用,所以必须采用拷贝的方式进行数据的传递。具体的操作过程如下图表示:

4.write设备操作

write函数方法也主要完成两件事:

(1)从应用程序提供的地址中取出数据到内核空间。

(2)访问硬件设备,将数据写入到设备中。

write函数方法直接对应于用户空间的write函数。

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

write函数方法的参数基本上和read函数方法类似,在此不再做解释。

那么实际上在此也存在一个问题,如何将数据从用户空间取出到内核空间使用???

实际上Linux内核中也提供了相应的方法函数,将用户空间的数据拷贝到内核空间进行使用,其方法为:copy_from_user。原型如下:

四、设备驱动注销

当内核中不再需要使用一个字符设备时,我们可以在内核中将相应的设备驱动程序进行卸载。那么就需要对其字符设备进行注销。Linux内核中为我们提供了cdev_del函数来完成字符设备的注销。其原型如下:

linux字符设备文件的打开操作,Linux字符设备驱动模型之字符设备初始化相关推荐

  1. linux使用设备文件的目录,Linux系统下的/dev目录

    dev是设备(device)的英文缩写./dev这个目录对所有的用户都十分重要.下面学习啦小编给大家分享详解Linux系统下的/dev目录,欢迎阅读: 详解Linux系统下的/dev目录: 在这个目录 ...

  2. linux 几个文件夹作用,linux下每一个文件夹的作用.docx

    目录结构及主要内容 "/"根冃录部分有以F子冃录: /usr 口录包含所有的命令.程序库.文档和英它文件.这些文件在正常操作中不会被改变的.这个目录也包含你的Linux 发行版本的 ...

  3. linux 穿件文件_关于Linux的25件事

    linux 穿件文件 今天是Linux 25年的历史,这是有史以来最成功的软件. 在本周的LinuxCon上,Linux基金会的Jim Zemlin在主题演讲中表达了钦佩,赞美和激动,他说:" ...

  4. linux major头文件_《Linux设备驱动程序》(四)——字符设备驱动(上)

    之前我们说过,Linux设备主要分为三类:字符设备.块设备和网络接口. 字符设备相对于另外两个设备更加容易理解,同时,这类设备也适合大多数简单的硬件设备,因此,接下来我们学习一下字符设备驱动. 字符驱 ...

  5. linux 设备文件分区命令,Linux常见设备及相应/dev/xxx文件名、Mount Point、挂载点、Mount命令、fstab、挂载分区(示例代码)...

    Linux 中的设备有2种类型:字符设备(无缓冲且只能顺序存取).块设备(有缓冲且可以随机存取).这些设备中,有些设备是对实际存在的物理硬件的抽象,而有些设备则是内核自身提供的功能(不依赖于特定的物理 ...

  6. linux磁盘混乱,Linux磁盘设备文件混乱源于Linux内核自身

    在Linux下往往会碰到这样的问题,磁盘的设备文件,比如/dev/sda, sdb, sdc等等在某些情况下会混乱掉,比如sda变成了sdb或者sdc变成了sdb等等,这样无形中会导致磁盘设备管理的混 ...

  7. linux查看usb设备文件,技术|在 Linux 系统里识别 USB 设备名字的 4 种方法

    对于初学者来说,在 Linux 系统里你必须掌握的技术之一就是识别出插入系统里的各种设备.这也许是你的系统硬盘.外部的存储设备或者是可移动设备,比如 USB 设备或 SD 闪存卡等. 现如今,使用 U ...

  8. linux设备文件的分类,Linux设备模型组件-类设备-设备类及subsystem

    Linux设备模型一.sysfs文件系统: sysfs文件系统是Linux2.6内核引入的,它被看成是与proc.devfs和devpty等同类别的文件系统,sysfs文件系统也是一个虚拟文件系统,它 ...

  9. linux文件系统中文件基本权限,Linux文件权限基本属性图文详解

    [概述] 在 Linux 系统中,不同的用户处于不同的地位,拥有不同的权限,为保护系统安全性,Linux 系统对不同的用户访问同一文件(包括目录文件)的权限做了不同的规定. Linux 系统的每一个文 ...

最新文章

  1. linux下uvc协议访问usb摄像头,Ubuntu调用USB摄像头
  2. Android实战——第三方服务之Bmob后端云的推送服务的集成和使用(三)
  3. 【Hibernate】Hibernate的jar包的用途
  4. windows安装XGBoost
  5. Python3——文件与异常
  6. 对github的初步认识以及对软件技术基础课程的期待
  7. graphics | 基础绘图系统(五)——plot函数功能再探和低级绘图函数
  8. 每日算法系列【LeetCode 424】替换后的最长重复字符
  9. LINUX下载编译nginx
  10. C# 读取txt文本数据
  11. 真正的人工智能能实现吗_如何实现真正的人工智能
  12. excel文件如何解密工作表保护密码
  13. OpenHarmony轻量系统开发【8】其它驱动开发示例
  14. ECharts之横向柱状图二
  15. matlab 控制命令,Matlab绘图基本控制命令
  16. 什么是抽象工厂模式?
  17. 计算机组成原理 十套,计算机组成原理十套卷答案白中英(74页)-原创力文档...
  18. python中矩阵的表示方法,稀疏矩阵在Python中的表示方法
  19. Python3.6中对爬取网页中的/XBB的处理
  20. vue 使用animate.css动画库

热门文章

  1. 两台xenserver 同一个vlan中的vm 不能ping通?
  2. 【Python】raise ValueError(Too many dimensions: %d %d. % (ndim, ndmax))问题
  3. RTSP播放器网页web无插件直播流媒体音视频播放器EasyPlayer-RTSP实现支持H265编码格式过程介绍
  4. matlab中print、fprintf、scanf、disp函数简要语法介绍
  5. windows下安装使用couchdb
  6. Linux中kill,pkill,killall和xkill命令汇总讲解
  7. VC++ 使用导入位图创建工具栏
  8. mysql+xml+注释,springboot整合mybatis完整示例, mapper注解方式和xml配置文件方式实现(我们要优雅地编程)...
  9. java linux so
  10. [原创分享] SocketCapture 网络抓包工具