基于linux内核的驱动开发

news/2024/9/19 11:06:09/

1 自动创建设备文件
   创建设备文件的方式:1 手动创建 sudo mknod /dev/haha0 c 250 0
                            2 自动创建--》使用内核函数
        linux内核为我们提供了一组内核函数,用于在模块加载时自动在/dev目录下创建响应的设备文件,并在卸载时删除该设备文件
         创建:1 class_create--》创建设备文件类
                2 device_create--》创建设备文件

        删除:3 class_destory--》删除设备文件类
               4 device_destory

      设备  主设备--》一类设备
            次设备--》该类设备中的某一个设备
     设备文件:一个设备文件---》一个次设备

        1  class_create--》创建设备文件类
            struct class *class_create(owner, name)
                owner:表示模块本身THIS_MODULE
                name:设备模块名
                 返回值:指向设备文件类的指针(struct class表示设备文件类)
        2 device_create--》创建设备文件
            struct device *device_create(struct class *class, struct device *parent,
                 dev_t devt, void *drvdata, const char *fmt, ...)
                *class:指向设备文件类的指针
                *parent:指向符设备的指针,一般为NULL
                devt:设备号 由主次设备号构成
                *drvdata:指向设备私有数据,若无,给NULL
                *fmt:设备文件名(haha0/haha1...)
                ...:可变参数
                返回值:成功 struct device *;失败err,需要判断
            3 class_destroy
            void class_destroy(struct class *cls)    
                    作用:删除设备文件类
                    *cls:指向设备文件类的指针    
            4 device_destroy
            void device_destroy(struct class *class, dev_t devt)
                作用:删除设备文件
                *class:指向设备文件类的指针
                devt:  设备号

           测试步骤:
            1 sudo insmod hello.ko
            2 dmesg |tail
            3 ls -l /dev/hah*--》查看是否生成了设备文件haha0/haha1?
            4 sudo ./test
            5 sudo ./test1
            6 sudo rmmod hello.ko
            7 ls -l /dev/hah*--->查看设备文件是否被删除

2 ioctl      man ioctl
    ioctl-->系统调用函数-->应用程序用它给设备&内核发送控制指令
     Linux内核给用户提供了两类系统调用函数:
            一类是数据操作函数,如read write...
            另一类是非数据操作函数,如ioctl,内核将对设备的操作交给了ioctl接口
                (换句话说,应用程序可以使用ioctl接口去控制底层设备)
        fd=open(“/dev/haha0”)-->250 0--->字符设备
    int ioctl(int d, int request, ...);
            d:文件描述符
            request:指令码
            ...:可变参数,若有,那么该参数是传给内核驱动的参数
            返回值:0成功 非0 失败
       
    命名码:1 可以自定义  1 0
               2 使用标准命名码  int--》4部分
                30-31:数据的控制方向(get/set)
                16-29:数据大小(14bit)
                8-15:设备类型(8bit)
                0-7:cmd-->命令码(区分命令的顺序序号)
                #define _IOC(dir,type,nr,size) \
                    (((dir)  << _IOC_DIRSHIFT) | \
                    ((type) << _IOC_TYPESHIFT) | \
                    ((nr)   << _IOC_NRSHIFT) | \
                    ((size) << _IOC_SIZESHIFT))

        #define _IO(type,nr)        _IOC(_IOC_NONE,(type),(nr),0)
        #define _IOR(type,nr,size)  _IOC(_IOC_READ,(type),(nr),sizeof(size))
        #define _IOW(type,nr,size)  _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
        #define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))

        common.h
            #define  TEST_CMD  0x1
            #define  TEST_CMD1  _IO('h',1)
            #define  TEST_CMD2  _IOW('h',2,int)
        
    应用:test.c
            fd=open("/dev/haha0",);
            ioctl(fd,TEST_CMD);
            ioctl(fd,TEST_CMD1);
            ioctl(fd,TEST_CMD2,12345);
                        
     驱动:HelloIoctl
            long (*unlocked_ioctl) (struct file *, unsigned int cmd, unsigned long arg)            
            {
                switch(cmd)
                    case TEST_CMD:{printk();break;}
                    case TEST_CMD1:{printk();break;}
                    case TEST_CMD2:{printk();break;}
            }
    
      测试步骤:
            1 sudo insmod hello.ko
            2 ls -l /dev/haha*
            3 sudo ./test
            4 dmesg |tail-->查看ioctl发的指令是否被解析?
            5 sudo rmmod hello.ko

3  驱动的互斥
   
    设备号:主设备+次设备
   主设备:代表一类设备--》驱动
   次设备:一类设备中的某一个设备--》使用驱动程序的终端个体
   多个子设备共用一个驱动程序,若多个子设备同时访问一个驱动程序时,就产生了竞态
    访问,那么如何解决驱动的竞态呢?linux内核提供了多种互斥方法:
        有:互斥锁 信号量 原子变量 自旋锁。。
    3.1 互斥锁
        mutex_t  mutex;-->应用层互斥锁
        1 定义互斥锁--》全局
        struct mutex  g_Mutex;-->内核互斥锁
        2 初始化互斥锁
            mutex_init(&g_Mutex);-->HelloModule
        3 加锁
            mutex_lock(&g_Mutex);-->HelloOpen
        4 解锁
            mutex_unlock(&g_Mutex);-->HelloClose
    3.2 信号量      
        1 定义信号量
            struct semaphore  sem;//内核信号量
        2 初始化信号量
            sema_init(&sem,1)-->HelloModule
        3 获取信号量-->HelloOpen
            down_interruptible(&sem)-->p操作 >0:sem--;函数返回  =0:阻塞进程
            down(&sem)
        4 释放信号量-->HelloClose
            up(&sem)--> v操作   sem_post(&semb)-->给sem++               
    3.3 原子变量   
        1 定义原子变量并初始化 
         atomic_t   a=ATOMIC_INIT(1);
        2 使用原子变量
        需要通过linux内核提供的函数来操作原子变量
        atomic_dec_and_test(&a): 该函数给原子变量a减1,然后测试其值是否等于0?
                                            如果为0,返回true;如果不为0,返回false。
        
        atomic_inc(&a):该函数给原子变量加1
        
                sudo ./test-->open("/dev/haha0")
                sudo ./test1--->open("/dev/haha1")

        helloOpen:
            if(!atomic_dec_and_test(&a))  1->0-->-1
            {
                atomic_inc(&a); 0
                return -EBUSY;
                //不能使用驱动
            }
            //可以使用驱动资源
            return 0;

        helloClose:
            atomic_inc(&a)0-->1

    3.4 自旋锁(忙等锁)
        1 定义自旋锁
            spinlock_t   g;-->自旋锁
        2 初始化自旋锁
            spin_lock_init(&g)-->HelloModule
        3 获取自旋锁
            spin_lock(&g)-->HelloOpen
           4 释放自旋锁
            spin_unlock(&g)-->HelloClose

    测试步骤:
        1 sudo insmod hello.ko
       2 dmesg |tail
       3 ls -l /dev/hah*
       4 sudo ./test-->write  sleep
       5 sudo ./test1--->read
       6 sudo rmmod hello.ko
 


http://www.ppmy.cn/news/26780.html

相关文章

vue-element-admin在git 上 clone 之后无法install

一. 无法install的原因因为vue-element-admin引入的富文本编辑插件所导致 由于tui-editor变更 名字 导致 依赖查询找不到对应的版本二. 解决的办法先删掉package.json中tui-editor:1.3.3找到 \src\components\MarkdownEditor\index.vue 把所有的import 替换成下面4个import cod…

【Kubernetes】【十九】安全认证

第九章 安全认证 本章节主要介绍Kubernetes的安全认证机制。 访问控制概述 ​ Kubernetes作为一个分布式集群的管理工具&#xff0c;保证集群的安全性是其一个重要的任务。所谓的安全性其实就是保证对Kubernetes的各种客户端进行认证和鉴权操作。 客户端 在Kubernetes集群…

23春招-mysql事务相关高频面试题

1、什么是事务 对于一个事务&#xff0c;要么事务内的sql全部执行&#xff0c;要么都不执行 2、 事务的特性ACID 原子性 整个事务中所有的操作要么全部提交成功&#xff0c;要么全部失败会滚。 一致性 数据库总是从一个一致性状态转换到另一个一致性状态。假如有三个sql语句…

Nginx 部署 Vue 项目以及 Vue 项目刷新出现 404 的问题(完整步骤)(亲测有效)

Nginx 部署 Vue 项目以及 Vue 项目刷新出现 404 的问题&#xff08;完整步骤&#xff09;&#xff08;亲测有效&#xff09; 1.流程步骤&#xff08;本教程下载的是1.20.2版本&#xff0c;放在D盘&#xff09; 1-1. 首先去官方下载 nginx &#xff0c;然后在当前目录下创建ht…

一文带你看透前端世界里的日期时间,对就是Date

很高兴我们能够通过不同空间&#xff0c;不同时间&#xff0c;通过这篇博客相识&#xff0c;那一定是一种缘分&#xff0c;一种你和狗哥的缘分。今天我希望通过这篇博客对我所熟知的前端世界里的日期时间做一个汇总&#xff0c;不止是代码上的汇总哦&#xff01; 目录 一、时区…

2023环翠区编程挑战赛中学组题解

T1. 出栈序列 题目描述 栈是一种“先进后出”的数据结构&#xff0c;对于一个序列1,2,...,n1,2, ...,n1,2,...,n&#xff0c;其入栈顺序是1,2,...n1,2, ...n1,2,...n&#xff0c;但每个元素出栈的时机可以自由选择。 例如111入栈、111出栈&#xff0c;222入栈、333入栈、333…

基于UIAutomation+Python+Unittest+Beautifulreport的WindowsGUI自动化测试框架common目录解析

文章目录1 框架工具说明2 技术栈说明3 框架截图4 源码解析/common目录4.1 common/baseinfo.py4.2 common/creenShot.py4.3 common/logOut.py4.4 common/reportOut.py4.5 common/sendMail.py注&#xff1a; 1、本文为本站首发&#xff0c;他用请联系作者并注明出处&#xff0c;谢…

Spring基础总结(中)

13. 实现 AOP 的方式 通过 ProxyFactory 实现&#xff0c;注意这和 Proxy 不同&#xff0c;如下的 User 类不需要实现接口 ProxyFactory proxyFactory new ProxyFactory(); proxyFactory.setTarget(new CService());proxyFactory.addAdvice(new MethodInterceptor() {public…

深度学习在视频多目标跟踪中的应用综述

文章目录摘要1、简介2、MOT:算法、指标和数据集2.1、MOT算法简介2.2、指标经典的指标完整的MOT指标ID 分数2.3、基准数据集3、MOT中的深度学习3.1、深度学习中的检测步骤3.1.1、Faster R-CNN3.1.2、SSD3.1.3、Other detectors3.1.4、cnn在检测步骤中的其他用途3.2、深度学习在特…

【MySQL】MySQL表的增删改查(进阶)

✨个人主页&#xff1a;bit me&#x1f447; ✨当前专栏&#xff1a;MySQL数据库&#x1f447; ✨算法专栏&#xff1a;算法基础&#x1f447; ✨每日一语&#xff1a;悟已往之不谏&#xff0c;知来者之可追。实迷途其未远&#xff0c;觉今是而昨非。 目 录&#x1f384;一. 数…

七大排序经典排序算法

吾日三省吾身&#xff1a;高否&#xff1f;富否&#xff1f;帅否&#xff1f;答曰&#xff1a;否。滚去学习!!!(看完这篇文章先)目前只有C和C的功底&#xff0c;暂时还未开启新语言的学习&#xff0c;但是大同小异&#xff0c;语法都差不多。目录&#xff1a;一.排序定义二.排序…

查询服务器tns文件路径,oracle数据库tns配置方法详解

查询服务器tns文件路径,oracle数据库tns配置方法详解 TNS简要介绍与应用 Oracle中TNS的完整定义&#xff1a;transparence Network Substrate透明网络底层&#xff0c; 监听服务是它重要的一部分&#xff0c;不是全部&#xff0c;不要把TNS当作只是监听器。 TNS是Oracle Net…

【单目标优化算法】烟花优化算法(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5;&#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密…

如何锁定Word文档部分文字不被修改

我们知道&#xff0c;想要保护Word文档的内容无法随意更改&#xff0c;可以设置“限制编辑”的保护模式。 那如果实际工作中&#xff0c;只需要固定的一部分内容不能编辑&#xff0c;可以实现吗&#xff1f;答案是肯定的&#xff0c;今天就来说说如何设置Word文档部分文字可修…

VS Code Spring 全新功能来了!

大家好&#xff0c;欢迎来到我们 2023 年的第一篇博客&#xff01;我们想与您分享几个与 Spring 插件、代码编辑和性能相关的激动人心的更新&#xff0c;让我们开始吧&#xff01; Spring 插件包的新入门演练 演练&#xff08;Walkthrough&#xff09; 是一种多步骤、向导式的体…

【软件测试】自动化测试该如何做?项目?技术团队?你真的会自动化吗......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 对于自动化测试&…

接入网关和隔离网关

文章目录1. 什么是网关&#xff1f;2. 网关的作用是什么&#xff1f;3. 接入网关和隔离网关1. 什么是网关&#xff1f; 网关&#xff08;Gateway&#xff09;是一种网络设备&#xff0c;通常用于将不同网络之间的流量进行转发和路由&#xff0c;将一个网络连接到另一个网络&…

第十三届蓝桥杯省赛 C++ A 组 F 题、Java A 组 G题、C组 H 题、Python C 组 I 题——青蛙过河(AC)

目录1.青蛙过河1.题目描述2.输入格式3.输出格式4.样例输入5.样例输出6.数据范围7.原题链接2.解题思路Ac_code1.C2.Java1.青蛙过河 1.题目描述 小青蛙住在一条河边, 它想到河对岸的学校去学习。小青蛙打算经过河里 的石头跳到对岸。 河里的石头排成了一条直线, 小青蛙每次跳跃…

双因素方差分析

一、案例与数据 一家大型商业银行在多地区设有分行&#xff0c;其业务主要是进行基础设施建设&#xff0c;国家重点项目建设&#xff0c;固定资产投资等项目的贷款。近年来&#xff0c;该银行的贷款额平稳增长&#xff0c;但不良贷款额也有较大比例的提高&#xff0c;这给银行…

C语言实现动态管理通讯录信息系统(静态通讯录plus版)

文章目录前言&#xff1a;一.动态管理思想1.通讯录结构体声明发生变化2.通讯录结构体初始化发生变化3.通讯录能够动态增容4.通讯录销毁数据二.优化通讯录可持续读写信息1.保存通讯录中的信息到文件中2.加载文件信息到通讯录中三.源码1.text.c2.contact.c3.contact.h前言&#x…