Linux驱动开发(一)--字符设备驱动开发基础

1、字符设备驱动简介
字符设备是 Linux 驱动中最基本的一类设备驱动,字符设备就是一个一个字节,按照字节 流进行读写操作的设备,读写数据是分先后顺序的。比如我们最常见的点灯、按键、IIC、SPI, LCD 等等都是字符设备,这些设备的驱动就叫做字符设备驱动。
如果在之前有学习RTOS的相关知识在这方面应该非常好理解,也就多了些IO文件操作而已。
Linux 中一切皆为文件,驱动加载成功以后会在“ /dev ”目录下生成一个相应的文件,应
用程序通过对这个名为“ /dev/xxx (xxx 是具体的驱动文件名字 ) 的文件进行相应的操作即可实
现对硬件的操作。比如现在有个叫做 /dev/led 的驱动文件,此文件是 led 灯的驱动文件。应用程
序使用 open 函数来打开文件 /dev/led ,使用完成以后使用 close 函数关闭 /dev/led 这个文件。 open 和 close 就是打开和关闭 led 驱动的函数,如果要点亮或关闭 led ,那么就使用 write 函数来操作,也就是向此驱动写入数据,这个数据就是要关闭还是要打开 led 的控制参数。如果要获取
led 灯的状态,就用 read 函数从驱动中读取相应的状态。
应用程序运行在用户空间,而 Linux 驱动属于内核的一部分,因此驱动运行于内核空间。
当我们在用户空间想要实现对内核的操作,比如使用 open 函数打开 /dev/led 这个驱动,因为用
户空间不能直接对内核进行操作,因此必须使用一个叫做“系统调用”的方法来实现从用户空
间“陷入”到内核空间,这样才能实现对底层驱动的操作。
如下是我们在编写字符驱动中的一个 最具有核心的函数,在驱动中都有与之对应的一个驱动函数,在 Linux 内核文件 include/linux/fs.h 中有个叫做 file_operations 的结构体, 此结构体就是 Linux 内核驱动操作函数集合。
struct file_operations {struct module *owner;loff_t (*llseek) (struct file *, loff_t, int);ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);int (*iterate) (struct file *, struct dir_context *);int (*iterate_shared) (struct file *, struct dir_context *);unsigned int (*poll) (struct file *, struct poll_table_struct *);long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);long (*compat_ioctl) (struct file *, unsigned int, unsigned long);int (*mmap) (struct file *, struct vm_area_struct *);int (*open) (struct inode *, struct file *);int (*flush) (struct file *, fl_owner_t id);int (*release) (struct inode *, struct file *);int (*fsync) (struct file *, loff_t, loff_t, int datasync);int (*fasync) (int, struct file *, int);int (*lock) (struct file *, int, struct file_lock *);ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);int (*check_flags)(int);int (*flock) (struct file *, int, struct file_lock *);ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);int (*setlease)(struct file *, long, struct file_lock **, void **);long (*fallocate)(struct file *file, int mode, loff_t offset,loff_t len);void (*show_fdinfo)(struct seq_file *m, struct file *f);
#ifndef CONFIG_MMUunsigned (*mmap_capabilities)(struct file *);
#endifssize_t (*copy_file_range)(struct file *, loff_t, struct file *,loff_t, size_t, unsigned int);int (*clone_file_range)(struct file *, loff_t, struct file *, loff_t,u64);ssize_t (*dedupe_file_range)(struct file *, u64, u64, struct file *,u64);
};
简单介绍一下 file_operation 结构体中比较重要的、常用的函数:
owner 拥有该结构体的模块的指针,一般设置为 THIS_MODULE
llseek 函数用于修改文件当前的读写位置。
read 函数用于读取设备文件。
write 函数用于向设备文件写入 ( 发送 ) 数据。
poll 是个轮询函数,用于查询设备是否可以进行非阻塞的读写。
unlocked_ioctl 函数提供对于设备的控制功能,与应用程序中的 ioctl 函数对应。
compat_ioctl 函数与 unlocked_ioctl 函数功能一样,区别在于在 64 位系统上,
32 位的应用程序调用将会使用此函数。在 32 位的系统上运行 32 位的应用程序调用的是
unlocked_ioctl
mmap 函数用于将设备的内存映射到进程空间中 ( 也就是用户空间 ) ,一般帧缓
冲设备会使用此函数,比如 LCD 驱动的显存,将帧缓冲 (LCD 显存 ) 映射到用户空间中以后应用
程序就可以直接操作显存了,这样就不用在用户空间和内核空间之间来回复制。
open 函数用于打开设备文件。
release 函数用于释放 ( 关闭 ) 设备文件,与应用程序中的 close 函数对应。
fasync 函数用于刷新待处理的数据,用于将缓冲区中的数据刷新到磁盘中。
aio_fsync 函数与 fasync 函数的功能类似,只是 aio_fsync 是异步刷新待处理的
数据。
在字符设备驱动开发中最常用的就是上面这些函数,关于其他的函数大家可以查阅相关文
档。我们在字符设备驱动开发中最主要的工作就是实现上面这些函数,不一定全部都要实现,
但是像 openreleasewriteread 等都是需要实现的,当然了,具体需要实现哪些函数还是要
看具体的驱动要求。
2、字符设备驱动开发基础
直接观察下述代码即可。
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>static int chrtest_open (struct inode *inodp, struct file *filp)
{return 0;
}static ssize_t chrtest_read (struct file *filp, char __user *buf, size_t, loff_t *offt)
{return 0;
}static ssize_t chrtest_write (struct file *filp, const char __user *buf, size_t, loff_t *offt)
{return 0;
}static int chrtest_release (struct inode *inodp, struct file *filp)
{return 0;
}static struct file_operations test_fops = {.owner   = THIS_MODULE,.open    = chrtest_open,.read    = chrtest_read,.write   = chrtest_write,.release = chrtest_release,
};static int __init xxx_init(void){int retvalue = 0;//设备号 名字 字符模型驱动的一个结构体retvalue = register_chrdev(200,"chrtest",&test_fops);if(retvalue < 0){// exit}return 0;
}static void __exit xxx_exit(void){unregister_chrdev(200,"chrtest");
}module_init(xxx_init);
module_exit(xxx_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("7yewh");

代码架构很简单,相信都能看懂,就不做具体解析了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/855442.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【自动驾驶技术】自动驾驶汽车AI芯片汇总——TESLA篇(FSD介绍)

0. 前言 按照国际惯例&#xff0c;首先声明&#xff1a;本文只是我自己学习的理解&#xff0c;虽然参考了他人的宝贵见解及成果&#xff0c;但是内容可能存在不准确的地方。如果发现文中错误&#xff0c;希望批评指正&#xff0c;共同进步。 本篇文章是这个自动驾驶汽车AI芯片系…

ObTypeIndexTable 在win7x86 和win10x64对比

当作备忘录,其他概念请自行搜索 对象类型和对象结构体类型 win7 x86win10 x64 寻找_object_type结构的地址 过程不一样,但是总归是在全局变量_ObTypeIndexTable数组中寻找 win7 的寻找过程

基于稀疏学习现代信号处理方法的旋转机械故障诊断(MATLAB)

通过对滚动轴承故障诊断研究现状及稀疏表示方法在滚动轴承故障诊断领域中应用现状的调研&#xff0c;发现稀疏表示方法与故障特征提取和故障分类的关联&#xff0c;针对故障诊断问题&#xff0c;通过构造合理的故障稀疏表示模型&#xff0c;选取适合的模型优化算法&#xff0c;…

Pycharm的基础使用

Pycharm的基础使用 一、修改主题 第一步&#xff1a;点击file->settings 第二步&#xff1a;找到Appearance&Behavior->Appearance->Theme选择主题 有五种主题可以选 二、修改默认字体和大小 第一步&#xff1a;打开设置与上面修改主题第一步一样&#xff1b…

C# 索引器与迭代器分部类详情

文章目录 一、迭代器二、查看Foreach执行中间语言三、foreach实现过程总结四、实现迭代器最常用的方法五、分布类概述及其使用六、索引器概述及声明七、索引器在类中的使用八、索引器在接口中的使用九、总结 一、迭代器 1、迭代器&#xff08;iterator&#xff09;解决的是集合…

零信任是对抗AI威胁的“解药”

人工智能的变革力量正在重塑众多行业的业务运营。通过机器人流程自动化&#xff08;RPA&#xff09;&#xff0c;人工智能正在将人力资源从重复的、基于规则的任务中解放出来&#xff0c;并将其重点放在战略性的、复杂的操作上。此外&#xff0c;人工智能和机器学习算法可以以前…

线程池内的交响乐章:揭秘线程间通信的奥秘

1. 线程池概述 线程池是一种多线程处理模式,旨在通过维护一组预先创建的线程,来优化线程的管理和调度。线程池中的线程是后台线程,它们被组织起来以处理添加到队列中的任务。线程池的主要目标是减少线程创建和销毁的开销,同时保证内核的充分利用和防止过分调度。 2. 线程池…

ASM之FieldVisitor创建变量

FieldVisitor使用abstract 修饰&#xff0c;用于创建变量&#xff0c;在使用时调用 ClassWriter.visitField即可创建FieldVisitor 方法介绍 visitField(Opcodes.ACC_PUBLIC, “str”, “Ljava/lang/String;”, null, “Hello World”) 第一个参数是修饰类型&#xff0c;第二…

数据库 |试卷1试卷2

1.数据库语言四大语句 4.四大类&#xff08;DDL、DML、DQL、DCL&#xff09;_中度ddl-CSDN博客 数据定义&#xff08;data defination language&#xff09; 查询、创建、删除、使用 #查询所有数据库 show databases;#查询当前数据库 select database();#创建数据库 create …

C++ 65 之 模版的局限性

#include <iostream> #include <cstring> using namespace std;class Students05{ public:string m_name;int m_age;Students05(string name, int age){this->m_name name;this->m_name age;} };// 两个值进行对比的函数 template<typename T> bool …

[思考记录]未来已近 - AI带来的变化,以及简单思考

最近在我们的内部知识库系统中引入了个比较有意思的功能——借助AI大模型&#xff0c;对思考总结类日志做要点提炼。这个想法来自涛哥&#xff0c;目前做了初步的验证性实现。尽管还没有对输出结果做调优&#xff0c;但已展现出的效果仍让我略感惊艳。不由地感叹&#xff0c;&a…

如何掌握 Java 中的安全机制,如权限控制和加密解密

Java是一门具有强大安全功能的编程语言&#xff0c;它内置了多种安全机制&#xff0c;包括权限控制、加密解密、认证授权等。 一、权限控制 权限控制是Java安全模型的重要组成部分&#xff0c;它主要通过Java安全管理器&#xff08;Security Manager&#xff09;和权限&#…

Python 数据可视化 多色散点图

Python 数据可视化 多色散点图 fig, ax plt.subplots() max_line max([max(merged_df[unif_ref_value]), max(merged_df[unif_rust_value])]) min_line min([max(merged_df[unif_ref_value]), max(merged_df[unif_rust_value])]) ax.plot([min_line, max_line], [min_line, …

【系统架构设计师】三、数据库系统(事务并发|封锁协议|数据库安全|商业智能|SQL语句)

目录 一、事务并发 1.1 事务概述 1.2 并发控制 1.3 封锁 1.3.1 X 封锁和 S 封锁 1.3.2 三级封锁协议 二、数据库安全 2.1 备份(转储)与恢复 2.2 备份分类 2.3 数据库故障 三、商业智能 3.1 数据仓库 3.2 数据仓库的结构-OLAP 3.3 数据挖掘 3.4 分布式数据库 四…

DDei在线设计器-API-DDei

DDei DDei是DDeiEditor的一个内置对象&#xff0c;实现了部分与图形显示有关但与设计器无关的功能、配置以及公共方法。 在图形内部一般不直接访问DDeiEditor&#xff0c;而是使用DDei&#xff0c;DDeiEditor的绝大多数初始化属性、回调函数等在DDei也能获取。。 本篇最后提供的…

研导AI写作:辅助创作的未来伙伴

人工智能&#xff08;AI&#xff09;写作技术正逐渐成为创作者们的强大助手。它不仅提高了写作效率&#xff0c;还拓展了创作的边界。本文将探讨AI写作的辅助作用&#xff0c;分析其如何在不同层面上促进人类创作的发展。 提升写作效率 AI写作的第一个辅助作用是提升写作效率…

GD32错误调试篇:串口通讯乱码/stm32移植到GD32后串口通讯乱码等问题

本文章基于兆易创新GD32 MCU所提供的2.2.4版本库函数开发 向上代码兼容GD32F450ZGT6中使用 后续项目主要在下面该专栏中发布&#xff1a; https://blog.csdn.net/qq_62316532/category_12608431.html?spm1001.2014.3001.5482 感兴趣的点个关注收藏一下吧! 电机驱动开发可以跳转…

小程序分页新写法

// pages/query/query.js import {request } from ../../utils/request; Page({/*** 页面的初始数据*/data: {tabClickIndex: ,page: 1,limit: 10,listData: []},/*** 生命周期函数--监听页面加载*/onLoad(options) {this.getList()},/*** 生命周期函数--监听页面初次渲染完成*…

【JS】上传文件显示文件的为空,显示的文件参数内容只有uid

上传的文件参数file里面只包含uid&#xff0c;没有其他信息 例子解决办法 例子 例如使用elment ui的el-upload组件上传文件&#xff0c;会导致上传的文件参数file里面只包含uid&#xff0c;没有其他信息&#xff0c;如图&#xff1a; 正确应为如下图&#xff1a; 解决办法 …

云上战场:ToDesk云电脑、青椒云、顺网云全面对决

前言 记得端午放假期间&#xff0c;我已经在旅游的路上了&#xff0c;老板突然发短信&#xff0c;让我给他画个图&#xff0c;我手上的战斗机已经是十年前的老古董了(平常一直用的公司电脑&#xff0c;也没想过要换)&#xff0c;压根满足不了老板的任务要求&#xff0c;不得已&…