嵌入式驱动学习第三周——如何优化驱动及提高驱动稳定性

前言

   在 Linux 中应用程序运行在用户空间,应用程序错误之后,并不会影响其他程序的运行,而驱动工作在内核层,是内核代码的一部分,当驱动出现问题之后,可能会导致整个系统的崩溃。所以在驱动中,需要对各种判断、预处理等进行排查等,本篇将对如何优化驱动稳定性和提高驱动效率进行学习。

   嵌入式驱动学习专栏将详细记录博主学习驱动的详细过程,未来预计四个月将高强度更新本专栏,喜欢的可以关注本博主并订阅本专栏,一起讨论一起学习。现在关注就是老粉啦!

目录

  • 前言
  • ioctl
    • ioctl初探
    • ioctl宏定义
  • 检测传递地址的有效性
    • 基础知识
    • 使用案例
  • 分支预测优化
    • 基础知识
    • 使用案例
  • 参考资料

ioctl

ioctl初探

   ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。

   如果不用ioctl的话,也可以实现对设备I/O通道的控制。例如,我们可以在驱动程序中实现write的时候检查一下是否有特殊约定的数据流通过,如果有的话,那么后面就跟着控制命令(一般在socket编程中常常这样做)。

   但是如果这样做的话,会导致代码分工不明,程序结构混乱,程序员自己也会头昏眼花的。所以,我们就使用ioctl来实现控制的功能。要记住,用户程序所作的只是通过命令码(cmd)告诉驱动程序它想做什么,至于怎么解释这些命令和怎么实现这些命令,这都是驱动程序要做的事情。

   一个ioctl命令由32比特位表示,每个比特位都有不同的含义,不同版本的内核定义可能有些差异:

比特位含义
31-3000-命令不带参数;01-命令需要把数据写入驱动;10-命令需要从驱动获取数据;11-命令既要写入数据又要获取方向
29-16如果命令带参数,则指定参数所占用的内存空间大小
31-30每个驱动全局唯一的幻数
31-30命令码

ioctl宏定义

构造ioctl命令

  • _IO(type, nr):用于构造无参数的命令号
  • _IOR(type, nr, datetype):用于构造从驱动程序中读取数据的命令号
  • _IOW(type, nr, datatype):用于构造向驱动程序写入数据的命令号
  • _IORW(type, nr, datatype):用于构造双向传输的命令号

解析ioctl命令

  • _IOC_DIR(cmd):获得传输方向位段的值
  • _IOC_TYPE(cmd):获得命令类型的值
  • _IOC_NR(cmd):获得命令的序号
  • _IOC_SIZE(cmd):获得数据的大小

   可以在驱动中通过上面的宏对传入的ioctl命令类型等参数进行判断,从而得到判断传入的参数是否正确,以此优化驱动的稳定性

if (_IOC_TYPE(cmd) != 'L') {printk("cmd type error\r\n");return -EFAULT;
}

   如上所示,可以通过上面的代码对传入参数的类型进行判断,如果传入的参数类型不为“L”,就返回错误码。

检测传递地址的有效性

基础知识

   我们需要检查用户空间指针是否可用

/** @description: 检查用户空间的指针是否可用* @param-type : 检查用户空间地址的权限,VERIFY_READ或者VERIFY_WRITE* 				 <VERIFY_READ>:驱动是否可以读取用户空间的指定地址* 				 <VERIFY_WRITE>: 驱动是否可以读取用户空间的指定地址, 驱动在指定用户空间地址既要读取也要写入,也是填这个* @param-addr : 用户空间地址* @param-size : 要操作的字节数,例如驱动从指定用户空间读一个int,那就是sizeof(int)* @return     : 1表示成功,0表示失败*/
int access_ok(int type, const void __user *addr, unsigned long size)

使用案例

   我们都知道,内核中不能直接用用户空间的东西,因为用户空间是实际地址,而内核中是虚拟地址,所以不能使用C语言中mallocmemcpy等函数,而是要先从用户空间拷贝到内核空间。为了保证安全性,在使用拷贝函数的时候需要用access_ok函数检查一下用户空间的地址是否具有权限。

if (access_ok(VERIFY_WRITE, buf, sizeof(buf)))retvalue = copy_from_user(databuf, buf, cnt);elsereturn -EFAULT;

分支预测优化

基础知识

   分支是使用if…else,但是执行的时候是按步骤执行的,即使判断条件很大概率不成立,也会消耗同样的时间。

   现在的CPU都有ICache和流水线机制,即预取指,运行当前指令时,ICache会预读取后面的指令,从而提高效率。但是如果分支的结果是跳转到其他指令,那预取吓一跳指令就浪费时间了。因此有likelyunlikely两个宏定义,让编译器总是大概率执行的代码放在靠前的位置,提高驱动的效率。

#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)

!!是C语言中处理逻辑表达式的一个技巧。因为C语言中没有布尔变量,所以布尔值是用整形来代替的,0为假,非0为真。当x为0时,!(x)为1,!!(x)为0,!!的运算没有什么意义;但当x为非0时(比如100),!(x)为0,!!(x)为1,这样就达到了将非0值(比如100)全部都映射为1的效果。

   __builtin_expect是编译器内建函数,原型为long __builtin_expect (long exp, long c)。该函数并不会改变exp的值,但是可以对if-else分支或者if分支结构进行优化。likely代表if分支大概率会发生,unlikely代表if分支大概率不会发生。

使用案例

   于是我们可以使用likely和unlikely优化一下上面的代码,因为从用户空间拷贝数据到内核空间的操作正常不会出错,因此可以如下优化:

if (!access_ok(VERIFY_WRITE, buf, sizeof(buf)))return -EFAULT;if (unlikely(copy_from_user(databuf, buf, cnt) == 0)) {return -EFAULT;
}

   用unlikely宏标记该分支很可能为假,假的话返回Linux错误码。

参考资料

[1] ioctl详解(Linux设备驱动程序模块)
[2] Linux驱动IO篇——ioctl设备操作
[3] access_ok()函数介绍
[4] C语言进阶——likely和unlikely

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

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

相关文章

【CSP考题扩展】前缀和/差分练习

【深进1.例1 求区间和】 题目描述 给定 n n n 个正整数组成的数列 a 1 , a 2 , ⋯ , a n a_1, a_2, \cdots, a_n a1​,a2​,⋯,an​ 和 m m m 个区间 [ l i , r i ] [l_i,r_i] [li​,ri​]&#xff0c;分别求这 m m m 个区间的区间和。 对于所有测试数据&#xff0c; n…

MySQL锁机制

概述 作为一名程序员(我是java开发)&#xff0c;锁是一个绕不开的话题。有读锁、写锁、排他锁、共享锁、红锁、可重入锁、自旋锁、公平锁、乐观锁、分段锁、偏向锁等等&#xff08;其实有些是一个意思&#xff09;。今天这里要说的是Mysql的锁机制(主要是innodb)&#xff0c;涉…

excel导入功能(适用于vue和react都可)

如图所示&#xff08;需求&#xff09;&#xff1a;点击导入excel后&#xff0c;数据自动新增到列表数据内 这里以vue3 andt 为例 template 标签内代码 &#xff1a; <a-uploadname"file":multiple"true":show-upload-list"false":customR…

3.3 ss-sp寄存器,栈的push和pop指令

汇编语言 1. 栈 栈是一种具有特殊的访问方式的存储空间它的特殊性就在于&#xff0c;最后进入这个空间的数据&#xff0c;最先出去。即先进后出 1.1 栈的基本操作 入栈&#xff1a;入栈就是将一个新的元素放到栈顶出栈&#xff1a;出栈就是从栈顶取出一个元素栈顶的元素总是…

C++ 智能指针的正确使用方式:unique_ptr VS shared_ptr

在实际的使用过程中&#xff0c;很多人都会有这样的问题&#xff1a; 不知道智能指针的具体使用场景无脑只使用 shared_ptr认为应该禁用 raw pointer(裸指针&#xff0c;即 Widget * 这种形式)&#xff0c;全部使用智能指针 本文将从这几方面讲解智能指针&#xff1a; 智能指…

Docker简单认识

目录 一、Docker概述 二、容器技术 2.1 容器与虚拟机的比较 2.2 容器和应用程序的比较 三、Docker和容器的关系 四、Docker和操作系统 五、总结 一、Docker概述 Docker 是一个开源的平台&#xff0c;用于开发、运送和运行应用程序。通过使应用程序与底层系统隔离&#x…

过滤器Filter和数组的filter()方法

在使用vue中的过滤器中的时候忽然想到数组中的fiter()方法&#xff0c;不禁想总结一下两者的用法和实现。 过滤器 在 Vue.js 中&#xff0c;过滤器是用于在模板中对数据进行格式化的一种机制。过滤器通过管道符 | 连接到表达式&#xff0c;例如&#xff1a; {{ message | filt…

服务雪崩,熔断,降级,限流之理解

服务雪崩是现状。 通过限流&#xff0c;熔断&#xff0c;降级等方式可以处理雪崩的问题。 服务限流&#xff0c;主要是为了保护服务的正常运行&#xff0c;大量请求过来&#xff0c;忙不过来&#xff0c;起码服务还能用。 服务熔断&#xff0c;是因为大量请求大多数失败或者…

机器学习常用框架

机器学习是人工智能的一个重要分支&#xff0c;它通过让计算机系统利用数据自我学习来改进任务执行的能力。在机器学习领域&#xff0c;有许多成熟的框架被广泛使用&#xff0c;这些框架提供了构建和训练机器学习模型的工具。以下是一些常用的机器学习框架&#xff1a; Tensor…

第2章 信息技术基础

本章学习要点 全面了解医院信息系统建设所涉及的主要信息技术以及这些技术的应用情况。 计算机与网络、信息技术与信息系统、数字媒体与数据存储技术、条形码(二维码)、RFID技术、云计算、APP技术 1.XML 可扩展标记语言与Access&#xff0c;Oracle和SQL Server等数据库不同…

【机器学习-01】机器学习基本概念与建模流程

机器学习的过程本质上是一个不断通过数据训练来提升模型在对应评估指标上表现的过程。在此过程中&#xff0c;为模型提供有效的反馈并基于这些反馈进行持续的调整是至关重要的。只有当这个过程顺利进行时&#xff0c;模型才能得到有效的训练&#xff0c;机器才能真正实现学习。…

修改vscode中代码的注释颜色

打开C盘、进入user目录&#xff0c;然后依次打开以下图片中的文件夹&#xff0c;在指定的文件中进行修改。 1. 2. 3. 4. 5. 6.

2049.不容易系列之(4)——考新郎

2048的升级 当nm时则全排错&#xff0c;与上题一样 当n>m时&#xff0c;则有n-m个是排对的&#xff0c;剩下m个全错 import java.util.*;public class Main {public static void main(String[] args) {Scanner scannernew Scanner(System.in);int num scanner.nextInt()…

解决ubuntu 22.04新内核6.5.0-15无法编译NVIDIA显卡驱动

这里的新内核应该包括6.5.*系列的 文章目录 遇到的问题&#xff1a; 遇到的问题&#xff1a; 今天我在安装NVIDIA显卡驱动发现了一个问题&#xff0c;主要日志如下所示&#xff1a; make[3]: *** [scripts/Makefile.build:251: /tmp/selfgz1310041/NVIDIA-Linux-x86_64-550.5…

昂贵的日用品和廉价的奢侈品

不同消费支出的心理账户之间具有非替代性 不同的消费支出分置在不同的心理账户中&#xff0c;不同消费心理账户的开支会受到所在账户预算约束的影响。 心理账户的预算控制机制 人们在分配总预算时&#xff0c;会将预算分门别类地分配到具体的心理账户中去。对于所有超过心理账…

【Docker】apisix 容器化部署

APISIX环境标准软件基于Bitnami apisix 构建。当前版本为3.8.0 你可以通过轻云UC部署工具直接安装部署&#xff0c;也可以手动按如下文档操作&#xff0c;该项目已经全面开源&#xff0c;可以从如下环境获取 配置文件地址: https://gitee.com/qingplus/qingcloud-platform qi…

Python+requests+excel 接口自动化测试框架

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、接口自动化测试框架 二、工程目录 三、Excel测试用例设计 四、基础数据base 封装post/get&a…

centos7磁盘管理,lvm挂载、扩容

一、centos7 磁盘挂载 默认盘符格式 centos7 默认文件格式xfscentos6 默认文件格式ext4centos5 默认文件格式ext3 1、/dev/vdb和/dev/mapper/lvm-data对比 1&#xff09;/dev/vdb /dev/vdb通常表示一个裸的块存储设备&#xff0c;比如一个硬盘或者虚拟机中的一个虚拟硬盘。…

【图像分类】基于深度学习的人脸表情识别(开心、悲伤、生气三个类别,ResNet网络)

写在前面: 首先感谢兄弟们的关注和订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。(专栏订阅用户订阅专栏后免费提供数据集和源码一份,超级VIP用户不在服务范围之内,不想订阅专栏的兄弟们可以私信…

Uni-app跟学笔记(五):uni-ui组件库的使用、项目打包(小程序、h5、APP)

文章目录 1&#xff09;uni-ui组件库的使用2&#xff09;项目打包1&#xff1a;微信小程序打包2&#xff1a;h5打包3&#xff1a;安卓打包 本博客为 uni-app 此门课的跟学笔记&#xff0c;目的是便于个人复习和对知识快速索引&#xff0c;源码素材可在均可在视频评论区找到 1&a…