ARM 驱动 1.22

linux内核等待队列wait_queue_head_t

头文件

  include <linux/wait.h>

定义并初始化

wait_queue_head_t r_wait;

init_waitqueue_head(&cm_dev->r_wait);

wait_queue_head_t 表示等待队列头,等待队列wait时,会导致进程或线程被休眠,一个等待队列头中可以有很多的等待队列元素。每个元素绑定一个进程或者线程。这里绑定进程或者线程的目的,是为了在执行wakeup时,知道应该唤醒谁。

Linux 字符设备驱动开发基础——read()、write() 相关函数解析

Linux字符设备驱动中,用户程序使用read()write() 相关函数时,内核会调用驱动程序中的的file_operations结构体中对应的read()write()函数。

file_operations,其是一个函数指针的集合,用于存放我们定义的用于操作设备的函数的指针,如果我们不定义,它默认保留为NULL。其中有最重要的几个函数,分别是open()read()write()ioctl(),下面分别对其进行解析。

1. 打开和关闭设备函数

(1)打开设备

int (*open) (struct inode *, struct file *);

在操作设备前必须先调用open函数打开文件,可以干一些需要的初始化操作。当然,如果不实现这个函数的话,驱动会默认设备的打开永远成功。打开成功时open返回0。

(2)关闭设备

int (*release) (struct inode *, struct file *);

当设备文件被关闭时内核会调用这个操作,当然这也可以不实现,函数默认为NULL。关闭设备永远成功。

2. read()、write() 函数

2.1 read() 函数

函数原型:

<span style="color:#000000"><span style="background-color:#282c34"><code class="language-c">ssize_t <span style="color:#999999">(</span><span style="color:#669900">*</span>read<span style="color:#999999">)</span> <span style="color:#999999">(</span><span style="color:#c678dd">struct</span> file <span style="color:#669900">*</span>filp<span style="color:#999999">,</span> <span style="color:#c678dd">char</span> __user <span style="color:#669900">*</span>buffer<span style="color:#999999">,</span> size_t size<span style="color:#999999">,</span> loff_t <span style="color:#669900">*</span>p<span style="color:#999999">)</span><span style="color:#999999">;</span> 
</code></span></span>

参数含义:

  • filp:待操作的设备文件file结构体指针;
  • buffer:为对应放置所读数据的缓冲区指针(即用户空间内存地址);
  • size:为要读取的数据长度;
  • p:为读的位置相对于文件开头的偏移,在读取信息后,这个指针一般都会移动,移动的值为要读取信息的长度值;
  • __user:是一个空的宏,主要用来显示的告诉程序员它修饰的指针变量存放的是用户空间的地址。

返回值:
成功实际读取的字节数,失败返回负值。
如果该操作为空,将使得read系统调用返回负EINVAL失败,正常返回实际读取的字节数。

 两个函数的作用分别是 从设备中获取数据发送数据给设备,应用程序中与之对应的也有 write() 函数及 read() 函数:

<span style="color:#000000"><span style="background-color:#282c34"><code class="language-c">len <span style="color:#669900">=</span> <span style="color:#61aeee">read</span><span style="color:#999999">(</span>fd<span style="color:#999999">,</span>buf<span style="color:#999999">,</span>len <span style="color:#999999">)</span>
<span style="color:#c678dd">static</span> ssize_t <span style="color:#61aeee">hello_read</span><span style="color:#999999">(</span><span style="color:#c678dd">struct</span> file <span style="color:#669900">*</span>filep<span style="color:#999999">,</span> <span style="color:#c678dd">char</span> __user <span style="color:#669900">*</span>buf<span style="color:#999999">,</span> size_t len<span style="color:#999999">,</span> loff_t <span style="color:#669900">*</span>pos<span style="color:#999999">)</span>
</code></span></span>
<span style="color:#000000"><span style="background-color:#282c34"><code class="language-c">len <span style="color:#669900">=</span> <span style="color:#61aeee">write</span><span style="color:#999999">(</span>fd<span style="color:#999999">,</span>buf<span style="color:#999999">,</span>size<span style="color:#999999">)</span>
<span style="color:#c678dd">static</span> ssize_t <span style="color:#61aeee">hello_write</span><span style="color:#999999">(</span><span style="color:#c678dd">struct</span> file <span style="color:#669900">*</span>filep<span style="color:#999999">,</span> <span style="color:#c678dd">const</span> <span style="color:#c678dd">char</span> __user <span style="color:#669900">*</span>buf<span style="color:#999999">,</span> size_t len<span style="color:#999999">,</span> loff_t <span style="color:#669900">*</span>pos<span style="color:#999999">)</span>
</code></span></span>

我们知道,应用程序工作在用户空间,而驱动工作在内核空间,二者不能直接通信的,那我们用何种方法进行通信呢?下面介绍一下内核中的 memcpy—copy_from_usercopy_to_user,虽然说内核中不能使用C库提供的函数,但是内核也有一个memcpy函数,用法跟C库中的一样。

2.3 copy_from_user函数与copy_to_user函数

从字面意义上理解:user是指用户,即用户空间。

file_operations结构体中实现的write函数,即2.2中的write() 函数中,用户空间向内核空间拷贝(写)数据需要使用copy_from_user函数。而用户空间从内核空间读取数据需要使用copy_to_user函数。两个函数定义在arch/arm/include/asm/uaccess.h中。

两个函数定义:

<span style="color:#000000"><span style="background-color:#282c34"><code class="language-c"><span style="color:#c678dd">static</span> <span style="color:#c678dd">inline</span> <span style="color:#c678dd">int</span> <span style="color:#61aeee">copy_from_user</span><span style="color:#999999">(</span><span style="color:#c678dd">void</span> <span style="color:#669900">*</span>to<span style="color:#999999">,</span> <span style="color:#c678dd">const</span> <span style="color:#c678dd">void</span> __user <span style="color:#c678dd">volatile</span> <span style="color:#669900">*</span>from<span style="color:#999999">,</span> <span style="color:#c678dd">unsigned</span> <span style="color:#c678dd">long</span> n<span style="color:#999999">)</span><span style="color:#999999">{</span>
	<span style="color:#61aeee">__chk_user_ptr</span><span style="color:#999999">(</span>from<span style="color:#999999">,</span> n<span style="color:#999999">)</span><span style="color:#999999">;</span>
	<span style="color:#61aeee">volatile_memcpy</span><span style="color:#999999">(</span>to<span style="color:#999999">,</span> from<span style="color:#999999">,</span> n<span style="color:#999999">)</span><span style="color:#999999">;</span>
	<span style="color:#c678dd">return</span> <span style="color:#98c379">0</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>

<span style="color:#c678dd">static</span> <span style="color:#c678dd">inline</span> <span style="color:#c678dd">int</span> <span style="color:#61aeee">copy_to_user</span><span style="color:#999999">(</span><span style="color:#c678dd">void</span> __user <span style="color:#c678dd">volatile</span> <span style="color:#669900">*</span>to<span style="color:#999999">,</span> <span style="color:#c678dd">const</span> <span style="color:#c678dd">void</span> <span style="color:#669900">*</span>from<span style="color:#999999">,</span> <span style="color:#c678dd">unsigned</span> <span style="color:#c678dd">long</span> n<span style="color:#999999">)</span><span style="color:#999999">{</span>
	<span style="color:#61aeee">__chk_user_ptr</span><span style="color:#999999">(</span>to<span style="color:#999999">,</span> n<span style="color:#999999">)</span><span style="color:#999999">;</span>
	<span style="color:#61aeee">volatile_memcpy</span><span style="color:#999999">(</span>to<span style="color:#999999">,</span> from<span style="color:#999999">,</span> n<span style="color:#999999">)</span><span style="color:#999999">;</span>
	<span style="color:#c678dd">return</span> <span style="color:#98c379">0</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
</code></span></span>

可以看到两个函数均是调用了 _memcpy() 函数:

static void volatile_memcpy(volatile char *to, const volatile char *from, unsigned long n){ while (n--) *(to++) = *(from++); }

其实在这里,我们可以思考,既然拷贝的功能上面的_memcpy() 函数就可以实现,为什么还要封装成 copy_to_user()copy_from_user()呢?

答案是_memcpy() 函数是有缺陷的,譬如我们在用户层调用函数时传入的不是字符串,而是一个不能访问或修改的地址,那样就会造成系统崩溃。

出于上面的原因,内核和用户态之间交互的数据时必须要先对数据进行检测,如果数据是安全的,才可以进行数据交互。上面的函数就是memcpy的改进版,在memcpy功能的基础上加上的检查传入参数的功能,防止有些人有意或者无意的传入无效的参数。

static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
 

参数:

  • to:目标地址(内核空间)
  • from:源地址(用户空间)
  • n:将要拷贝数据的字节数

返回值:
成功返回0,失败返回没有拷贝成功的数据字节数

static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)

参数:

  • to:目标地址(用户空间)
  • from:源地址(内核空间)
  • n:将要拷贝数据的字节数

返回值:

成功返回0,失败返回没有拷贝成功的数据字节数

 Linux中将设备分为三大类:字符设备(I2C、USB、SPI等)、块设备(存储器相关的设备如EMMC、SD卡、U盘等)和网络设备(网络相关的设备WIFI等)。

杂项设备归属于字符设备,每个设备节点都有主设备号和次设备号 ,设备号是识别设备的一种方式,Linux系统中有很多杂项设备,而杂项设备的主设备号固定为10。                                   使用命令<cat /proc/misc>可以查看各杂项设备。

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

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

相关文章

springsecurity集成kaptcha功能

前端代码 本次采用简单的html静态页面作为演示&#xff0c;也可结合vue前后端分离开发&#xff0c;复制就可运行测试 项目目录 登录界面 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</…

详谈c++智能指针!!!

文章目录 前言一、智能指针的发展历史1.C 98/03 的尝试——std::auto_ptr2.std::unique_ptr3.std::shared_ptr4.std::weak_ptr5.智能指针的大小6.智能指针使用注意事项 二、智能指针的模拟实现三、C11和boost中智能指针的关系 前言 C/C 语言最为人所诟病的特性之一就是存在内存…

Quartus II使用小技巧

工程结构&#xff1a; 在建立完某项设计的文件后&#xff0c;依次在其里面新建四个文件夹&#xff0c;分别为&#xff1a;rtl、qprj、msim、doc。 rtl文件夹用于存放设计的源文件。 doc文件夹用于存放设计的一些文档性的资料。 qprj文件夹用于存放quaruts 工程以及quartus生…

陪玩系统:最新商业版游戏陪玩语音聊天系统3.0商业升级独立版本源码

首发价值29800元的最新商业版游戏陪玩语音聊天系统3.0商业升级独立版本源码 &#xff08;价值29800&#xff09;最新陪玩3.0独立版本 &#xff0c;文件截图 结尾将会附上此系统源码以及详细搭建教程包含素材图仅用于学习使用 陪玩系统3.0独立升级版正式发布&#xff0c;此版本…

项目管理中如何有效沟通?项目管理有效沟通指南

无论是少数人的小型企业还是拥有数十名员工的大公司&#xff0c;有效的沟通对于确保每个人都参与并准备好在项目中实现相同的目标至关重要。 然而&#xff0c;由于沟通不畅&#xff0c;似乎在翻译中总是丢失一些东西。事实上&#xff0c;根据布兰迪斯大学的一项研究&#xff0c…

【复现】SpringBlade SQL 注入漏洞_22

目录 一.概述 二 .漏洞影响 三.漏洞复现 1. 漏洞一&#xff1a; 四.修复建议&#xff1a; 五. 搜索语法&#xff1a; 六.免责声明 一.概述 SpringBlade 是由一个商业级项目升级优化而来的SpringCloud微服务架构&#xff0c;采用Java8 API重构了业务代码&#xff0c;完全…

一文梳理Windows自启动位置

不同版本的Windows开机自启动的位置略有出入&#xff0c;一般来说&#xff0c;Windows自启动的位置有&#xff1a;自启动文件夹、注册表子键、自动批处理文件、系统配置文件等。如果计算机感染了木马&#xff0c;很有可能就潜伏于其中&#xff01;本文将说明这些常见的Windows开…

GitHub README-Template.md - README.md 模板

GitHub README-Template.md - README.md 模板 1. README-Template.md 预览模式2. README-Template.md 编辑模式References A template to make good README.md. https://gist.github.com/PurpleBooth/109311bb0361f32d87a2 1. README-Template.md 预览模式 2. README-Templat…

CHS_02.2.2.2+调度的目标 调度算法的评价指标

CHS_02.2.2.2调度的目标 调度算法的评价指标 知识总览CPU利用率系统吞吐量周转时间等待时间响应时间 知识回顾 在这个小节中 我们会学习一系列用于评价一个调度算法好坏的一些评价指标 知识总览 包括cpu利用率 系统吞吐量 周转时间 等待时间和响应时间 那在学习的过程中 要注意…

20240122在WIN10+GTX1080下使用字幕小工具V1.2的使用总结(whisper)

20240122在WIN10GTX1080下使用字幕小工具V1.2的使用总结 2024/1/22 19:52 结论&#xff1a;这个软件如果是习作&#xff0c;可以打101分&#xff0c;功能都实现了。 如果作为商业软件/共享软件&#xff0c;在易用性等方面&#xff0c;可能就只能有70分了。 【百分制】 可选的改…

makefile 编译动态链接库使用(.so库文件)

makefile 编译动态链接库使用&#xff08;.so库文件&#xff09; 动态链接库:不会把代码编译到二进制文件中&#xff0c;而是在运行时才去加载&#xff0c; 好处是程序可以和库文件分离&#xff0c;可以分别发版&#xff0c;然后库文件可以被多处共享 动态链接库 动态&#…

macbookpro怎么恢复出厂设置2024最新恢复方法汇总

可能你的MacBook曾经是高性能的代表&#xff0c;但是现在它正慢慢地逝去了自己的光芒&#xff1f;随着逐年的使用以及文件的添加和程序的安装&#xff0c;你的MacBook可能会开始变得迟缓卡顿&#xff0c;或者失却了以往的光彩。如果你发现你的Mac开始出现这些严重问题&#xff…

牛客周赛 Round 20 解题报告 | 珂学家 | 状压DP/矩阵幂优化 + 前缀和的前缀和

前言 整体评价 这场比赛很特别&#xff0c;是牛客周赛的第20场&#xff0c;后两题难度直线飙升了。 前四题相对简单&#xff0c;E题是道状压题&#xff0c;历来状压题都难&#xff0c;F题压轴难题了&#xff0c;感觉学到了不少。 A. 赝品 先求的最大值 然后统计非最大值的个…

Haar小波下采样模块

论文原址&#xff1a;Haar wavelet downsampling: A simple but effective downsampling module for semantic segmentation - ScienceDirect 原文代码&#xff1a;HWD/HWD.py at main apple1986/HWD (github.com) 介绍 深度卷积神经网络 &#xff08;DCNN&#xff09; 通…

CPMS靶场练习

关键&#xff1a;找到文件上传点&#xff0c;分析对方验证的手段 首先查看前端发现没有任何上传的位置&#xff0c;找到网站的后台&#xff0c;通过弱口令admin 123456可以进入 通过查看网站内容发现只有文章列表可以进行文件上传&#xff1b;有两个图片上传点 图片验证很严格…

《WebKit 技术内幕》学习之六(2): CSS解释器和样式布局

2 CSS解释器和规则匹配 在了解了CSS的基本概念之后&#xff0c;下面来理解WebKit如何来解释CSS代码并选择相应的规则。通过介绍WebKit的主要设施帮助理解WebKit的内部工作原理和机制。 2.1 样式的WebKit表示类 在DOM树中&#xff0c;CSS样式可以包含在“style”元素中或者使…

SpringBoot异常处理和单元测试

学习目标 Spring Boot 异常处理Spring Boot 单元测试 1.SpringBoot异常处理 1.1.自定义错误页面 SpringBoot默认的处理异常的机制&#xff1a;SpringBoot 默认的已经提供了一套处理异常的机制。一旦程序中出现了异常 SpringBoot 会向/error 的 url 发送请求。在 springBoot…

移动开发行业——鸿蒙OS NEXT开出繁花

1月18日&#xff0c;华为宣布HarmonyOS NEXT开发者预览版开放申请&#xff0c;根据官方注解&#xff0c;这个版本的鸿蒙系统有个更通俗易懂的名字——“星河版”&#xff0c;也被称为“纯血”鸿蒙。 根据官方解释&#xff0c;之所以取名星河版&#xff0c;寓意鸿蒙OS NEXT就像…

28、web攻防——通用漏洞SQL注入HTTP头XFFCOOKIEPOST请求

文章目录 $_GET&#xff1a;接收get请求&#xff0c;传输少量数据&#xff0c;URL是有长度限制的&#xff1b; $_POST&#xff1a;接收post请求&#xff1b; $_COOKIE&#xff1a;接收cookie&#xff0c;用于身份验证&#xff1b; $_REQUEST&#xff1a;收集通过 GET 、POST和C…

线性代数:矩阵运算(加减、数乘、乘法、幂、除、转置)

目录 加减 数乘 矩阵与矩阵相乘 矩阵的幂 矩阵转置 方阵的行列式 方阵的行列式&#xff0c;证明&#xff1a;|AB| |A| |B| 加减 数乘 矩阵与矩阵相乘 矩阵的幂 矩阵转置 方阵的行列式 方阵的行列式&#xff0c;证明&#xff1a;|AB| |A| |B|