树莓派学习笔记(十二)Linux驱动认知及编译加载驱动

文章目录

  • 一、Linux驱动认知
  • 二、内核空间
    • 1、如何找到相关的驱动
    • 2、主设备号和次设备号
    • 3、驱动链表:管理所有设备的驱动
    • 4、驱动插入链表的顺序由设备号检索
    • 5、驱动代码的开发
  • 三、驱动编写、编译、测试
  • 四、驱动阶段性总结

一、Linux驱动认知

Linux驱动分为用户空间、内核空间和硬件
请添加图片描述
用户空间:分为App和C library

  • (1)App:cp、ftp项目、C基础、C库、文件、进程、进程间通信、线程、网络

  • (2)C library:指C库,比如:open() read() write() fork() pthread() socket()等等,c库提供的API调用内核态,支配内核干活。(提供了app支配内核干活的接口)

二、内核空间

  • Linux下一切皆文件
  • 设备都拥有自己对应的驱动程序

1、如何找到相关的驱动

(1)文件名

(2)设备号:主设备号和次设备号

2、主设备号和次设备号

请添加图片描述Linux的设备管理是和文件系统紧密结合的,各种设备都以文件的形式存放在/dev目录下,称为设备文件。应用程序可以打开、关闭和读写这些设备文件,完成对设备的操作,就像操作普通的数据文件一样。为了管理这些设备,系统为设备编了号,每个设备号又分为主设备号和次设备号。主设备号用来区分不同种类的设备(比如手机品牌种类有华为、苹果、oppo、vivo等),而次设备号用来区分同一类型的多个设备(比如华为品牌的mate30、mate40、mate 50手机等)。对于常用设备,Linux有约定俗成的编号,如硬盘的主设备号是3

3、驱动链表:管理所有设备的驱动

(1)添加:编写完驱动程序,加载到内核

(2)查找:调用驱动程序,应用层用户空间去open()

4、驱动插入链表的顺序由设备号检索

在这里插入图片描述

5、驱动代码的开发

1、添加驱动

(1)设备名
(2)设备号:主设备号和此设备号
(3)设备驱动函数(操作寄存器来驱动I/O口)

2、 调用驱动过程
请添加图片描述

  • 用户程序调用open函数,会触发中断异常(软中断,中断号0x80表示系统调用),进入内核态,调用sys_call
  • 穿透虚拟文件系统(VFS),调用sys_open函数根据文件名背后的设备号去驱动链表中找到对应的驱动,调用驱动的相关函数,实现具体操作

Linux之中,一切皆文件,硬件设备(鼠标,键盘,led,屏幕,flash,内存,网卡),IO口,串口
这些都需要驱动程序来进行调用,上层只需要通过open,read,write函数来操作,而操作的对象是文件还是设备,这就需要驱动程序的运行请添加图片描述

三、驱动编写、编译、测试

1. 驱动编写:
文件命名为pin4driver.c

手动生成设备

sudo mknod cl c 8 1

请添加图片描述

#include <linux/fs.h>   //file_operations声明
#include <linux/module.h>    //module_init  module_exit声明
#include <linux/init.h>      //__init  __exit 宏定义声明
#include <linux/device.h>  //class  devise声明
#include <linux/uaccess.h>   //copy_from_user 的头文件
#include <linux/types.h>     //设备号  dev_t 类型声明
#include <asm/io.h>          //ioremap iounmap的头文件
 
static struct class *pin4_class;  
static struct device *pin4_class_dev;
 
static dev_t devno;                //设备号
static int major =231;       //主设备号
static int minor =0;      //次设备号
static char *module_name="pin4";   //模块名
 
//read
static int pin4_read(struct file *file1,char __user *buf,size_t size,loff_t *ppos)
{
        printk("pin4_read\n");
        return 0;
}
 
 
//led_open函数
static int pin4_open(struct inode *inode,struct file *file)
{
   printk("pin4_open\n");  //内核的打印函数和printf类似
   return 0;
}
 
//led_write函数
static ssize_t pin4_write(struct file *file,const char __user *buf,size_t count, loff_t *ppos)
{
   printk("pin4_write\n");
   return 0;
}
 
static struct file_operations pin4_fops = {
   .owner = THIS_MODULE,
   .open  = pin4_open,
   .write = pin4_write,
   .read  = pin4_read,
};
 
int __init pin4_drv_init(void)   //真时驱动入口   
{
    int ret;
    devno = MKDEV(major,minor);  //1、创建设备号
    ret   = register_chrdev(major, module_name,&pin4_fops);  //3、注册驱动  告诉内核,把这个驱动加入到内核驱动的链表中
    pin4_class=class_create(THIS_MODULE,"myfirstdemo");      //代码在dev下自动生成设备
    pin4_class_dev =device_create(pin4_class,NULL,devno,NULL,module_name);  //创建设备文件
    return 0;
}
 
void __exit pin4_drv_exit(void)
{
 device_destroy(pin4_class,devno);
 class_destroy(pin4_class);
 unregister_chrdev(major, module_name);  //卸载驱动
}
 
module_init(pin4_drv_init);  //入口,内核加载该驱动的时候,这个宏会被调用
module_exit(pin4_drv_exit);
MODULE_LICENSE("GPL v2");

2. 驱动编译:
2.1 将驱动代码拷贝到driver/char目录下
请添加图片描述

2.2 修改该目录下的Makefile(在首行加上下面语句),表示需要编译该驱动文件

  • (1)输入指令: vi Makefile

  • (2)然后在Makefile文件内加一条:obj-m += pin4driver2.o

	obj-m    += pin4driver.o //obj-m表示以模块形式编译生成.ko文件
							 //pin4driver.o是驱动代码pin4driver.c的.o文件				

在这里插入图片描述
2.3返回内核目录下进行编译

	ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make modules

编译成功后在driver/char目录下出现pin4driver.ko驱动文件
请添加图片描述
3. 驱动测试
3.1 将xxx.ko驱动文件通过scp命令发送给树莓派

	scp pin4driver.ko pi@192.168.0.123:/home/pi

3.2 装载内核驱动:sudo insmod xxx.ko

sudo insmod pin4driver.ko

3.2.1 编译一个测试代码pin4test.c,然后把测试代码远程拷贝到树莓派的根目录

测试代码内容如下:

#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>

int main()
{
        int fd;
        int cmd;
        int data;
        fd = open("/dev/pin4",O_RDWR);

        if(fd < 0){
                printf("open failed\n");
                perror("reson:");


        }else{

                printf("open success\n" );
        }
        printf("input command: 1/0\n1:set pin4 high\n0:set pin4 low\n" );
        scanf("%d",&cmd);
        if (cmd == 1)
        {
                data = 1;
        }
        if (cmd == 0)
        {
                data = 0;
        }
        printf("data= %d\n",data);
        fd= write(fd,&data,1);

}
  • 开始编译测试代码,并重新命名为pin4test
arm-linux-gnueabihf-gcc pin4test.c -o pin4test

请添加图片描述

  • 把测试代码pin4test远程拷贝到树莓派的根目录
scp pin4test pi@192.168.0.123:/home/pi

3.3 为设备文件添加访问权限

  • 装载成功后将在/dev目录下生成设备(例/dev/pin4,需要给该文件添加访问权限:sudo chmod 666 /dev/pin4 )
sudo chmod 666 /dev/pin4
  • 原因:内核驱动是由通过sudo命令管理员装载的,默认只有管理员有访问权限

3.4 运行测试程序调用驱动(测试程序参考博文:基于框架编写驱动)

  • 运行./pin4test文件

3.5 通过命令dmesg查看打印的信息
(Dmesg用于显示内核环形缓冲区的内容,内核在其中存储各种消息)

补充:
查看内核模块:lsmod
卸载内核驱动:sudo rmmod xxx(不需要写.ko)

四、驱动阶段性总结

(1)内核驱动基本框架:

  • 驱动代码编写:

  • 参考pin4driver.c:

(2)内核驱动编译:

  • 把驱动代码拷贝至 driver/char
  • 修改Makefile ,告诉编译器,要编译该驱动文件,驱动代码文件放在哪个目录下就修改哪个目录下的Makefile文件
  • ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make modules

(3)驱动测试步骤:

内核驱动装载:

  • sodu insmod xxx.ko
  • 内核驱动卸载:
  • sodu rmmod xxx 不需要写ko
  • 查看内核模块:
    lsmod

(4)验证步骤:

  • 装载驱动
  • 驱动装载后生成设备,比如:/dev/pin4,通过
  • sudo chmod 666 /dev/pin4 添加访问权限
  • 运行测试程序pin4text调用驱动
  • 内核的printk是内核层的printf,通过dmesg查看打印信息。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

TCP网络事件模型的封装2.0

TCP网络事件模型的封装2.0 最近学习了TCP网络模型的封装&#xff0c;其中运用的封装技术个人感觉有点绕 在反复读代码、做思维导图下初步理解了这套封装模型&#xff0c;不禁感叹原来代码还能这样写&#xff1f;神奇&#xff01; 为此将源码分享出来并将流程图画出&#xff…

FITC-PEG-SH,荧光素-聚乙二醇-巯基的用途:用于修饰氨基酸,蛋白质等

FITC-PEG-SH 荧光素聚乙二醇巯基 英文名称&#xff1a;Fluorescein (polyethylene glycol)Thiol 中文名称&#xff1a;荧光素聚乙二醇巯基 外观: 黄色液体、半固体或固体&#xff0c;取决于分子量。 溶剂&#xff1a;溶于水等其他常规性有机溶剂 激光/发射波长&#xff1a…

ChatGPT使用案例之自然语言处理

ChatGPT使用案例之自然语言处理 自然语言处理被誉为“人工智能皇冠上的明珠”&#xff0c;这句话就已经说明了自然语言处理在整个人工智能体系中的重要性&#xff0c;自然语言处理&#xff08;Natural Language Processing&#xff0c;NLP&#xff09;是一种涉及计算机和人类自…

联想小新 青春版-14笔记本电脑重装系统教程

在使用笔记本电脑的过程中&#xff0c;我们难免会遇到一些问题&#xff0c;比如系统崩溃、病毒感染等等。这时候&#xff0c;我们就需要重装系统来解决这些问题。而联想小新 青春版-14笔记本电脑的系统重装方法&#xff0c;就是我们需要掌握的技能之一。本文将详细介绍如何重装…

python怎么自学

其实0基础选择python学习入行的不在少数&#xff0c;Python近段时间一直涨势迅猛&#xff0c;在各大编程排行榜中崭露头角&#xff0c;得益于它多功能性和简单易上手的特性&#xff0c;让它可以在很多不同的工作中发挥重大作用。 正因如此&#xff0c;目前几乎所有大中型互联网…

element-plus官网访问太慢 下载文档到本地部署 实现快速查阅

我只是吐槽下 element基于githup pages这个部署文档地址 本来访问就慢,然后吧这个文档看的人还很多,导致更慢了 经常卡半天才出来文档地址 文档地址: https://github.com/element-plus/element-plus/tree/gh-pages 文档的地址(你直接下载下来 想跑起来的话可能需要更改文档的路…

【C++】IO流 + 空间配置器(了解)

文章目录&#x1f4d6; 前言1. IO流1.1 C语言的输入和输出&#xff1a;1.2 流的概念及特性&#xff1a;1.3 自定义类型隐式类型转换&#xff1a;1.4 在线OJ中的输入和输出&#xff1a;1.5 CIO流对文件的操作&#xff1a;1.6 stringstream介绍&#xff1a;2. 空间配置器2.1 什么…

安科瑞智能照明控制系统在工厂的应用

安科瑞 安科瑞 李亚娜 1&#xff5c;概述 安科瑞智能照明控制解决方案ALIBUS&#xff08;Acrel Lighting intelligent Bus&#xff09;基于成熟的RS485通讯控制技术&#xff0c;同时创新地引入了载波侦听和冲突碰撞检测机制&#xff0c;多机间实现了实时双向通讯&#xff0c;线…

Java设计模式-9 、策略模式

策略模式 策略模式&#xff08;Strategy Pattern&#xff09;属于对象的⾏为模式。其⽤意是针对⼀组算 法&#xff0c;将每⼀个算法封装到具有共同接⼝的独⽴的类中&#xff0c;从⽽使得它们可以 相互替换。策略模式使得算法可以在不影响到客户端的情况下发⽣变化。 其主要⽬的…

基于Python长时间序列遥感数据处理及在全球变化、物候提取、植被变绿与固碳分析、生物量估算与趋势分析等领域中的应用

植被是陆地生态系统中最重要的组分之一&#xff0c;也是对气候变化最敏感的组分&#xff0c;其在全球变化过程中起着重要作用&#xff0c;能够指示自然环境中的大气、水、土壤等成分的变化&#xff0c;其年际和季节性变化可以作为地球气候变化的重要指标。此外&#xff0c;由于…

手敲Mybatis(八)-参数处理器

前言在之前的章节里边&#xff0c;类PreparedStatementHandler我们还没有处理在执行Sql时的参数&#xff0c;目前是硬编码写死存储的&#xff0c;如&#xff1a;ps.setLong()&#xff0c;这里就只能处理long类型的数据因为写死了&#xff0c;我们需要处理下让它支持设置不同的数…

【Linux 网络编程4】网络层--UDP/TCP协议,3次握手4次挥手、粘包问题等

netstat命令-n.拒绝显示别名&#xff0c;能显示数字的全部转化成数字(IPPORT)-l 仅列出有在 Listen (监听) 的服务的状态-p 显示建立相关链接的程序名&#xff08;pid&#xff09;-t 仅显示tcp相关选项-u 仅显示udp相关选项 2.UDP协议2.1.全双工和半双工的区别全双工&#xff1…

了解Session、LocatStorage、Cache-Control、ETag区别

一、cookie与session有什么区别&#xff1f; 1. 由于HTTP协议是无状态的协议&#xff0c;所以服务端需要记录用户的状态时&#xff0c;就需要用某种机制来识具体的用户&#xff0c;这个机制就是Session.典型的场景比如购物车&#xff0c;当你点击下单按钮时&#xff0c;由于HT…

SpringBoot学习笔记(4)-分析 SpringBoot 底层机制

文章目录4. 分析 SpringBoot 底层机制4.1 Tomcat启动分析4.2 创建Spring 容器4.3 将Tomcat 和 Spring 容器关联&#xff0c;并启动 Spring 容器4.4 扩展-debug查看 ac.refresh()4. 分析 SpringBoot 底层机制 【Tomcat 启动分析 Spring 容器初始化Tomcat 如何关联 Spring 容器…

微软分享修复WinRE BitLocker绕过漏洞的脚本

微软发布了一个脚本&#xff0c;可以更轻松地修补 Windows 恢复环境 (WinRE) 中的 BitLocker 绕过安全漏洞。 此 PowerShell 脚本 (KB5025175) 简化了保护 WinRE 映像以防止试图利用CVE-2022-41099漏洞的过程&#xff0c;该漏洞使攻击者能够绕过 BitLocker 设备加密功能系统存…

jvm03垃圾回收篇

p134 垃圾回收相关章节的说明 p135 什么是GC 为什么需要GC P136 了解早起垃圾回收行为 p137 java自动内存管理介绍 p138垃圾回收相关算法概述 p139引用计数算法的原理及优缺点 p140 python引用计数实施方案 p141 可达性分析算法与GC ROOTS p142 对象的finalization机制 p143 代…

【MyBatis】字段名和属性名不同时,如何处理

目录 前言 1、返回类型&#xff1a;resultType 2、返回字典映射&#xff1a;resultMap 2.1、字段名和属性名不同怎么处理 解决方案一&#xff1a;使用resultMap 解决方案二&#xff1a;使用as起别名 3、多表查询 总结&#xff1a; 前言 在之前的文章中&#xff0c;我们可…

TXT 和 SEV技术小知识

1.Intel TXT 可信执行技术(Trusted Execute Technology&#xff0c;TXT)是Intel公司的可信计算技术&#xff0c;主要通过改造芯片组和CPU&#xff0c;增加安全特性&#xff0c;通过结合一个基于硬件的安全设备—可信平台模块(Trusted Platform Module&#xff0c;TPM)&#xf…

蓝桥杯C/C++VIP试题每日一练之Sine之舞

💛作者主页:静Yu 🧡简介:CSDN全栈优质创作者、华为云享专家、阿里云社区博客专家,前端知识交流社区创建者 💛社区地址:前端知识交流社区 🧡博主的个人博客:静Yu的个人博客 🧡博主的个人笔记本:前端面试题 个人笔记本只记录前端领域的面试题目,项目总结,面试技…

Python 之列表推导式

文章目录参考描述列表推导式举个栗子基本形式一般式基本形式&#xff08;高阶&#xff09;判断使用逻辑运算符笛卡尔积拆解变量污染列表推导式参考 项目描述流畅的 PythonLuciano Ramalho 著 / 安道 吴珂 译搜索引擎Bing 描述 项目描述Python3.10.6 列表推导式 列表推导式是…