内核驱动程序中如何读写user space的文件,方便调试程序
需要在Linux kernel--大多是在需要调试的驱动程序--中读写文件数据。但是在kernel中操作文件没有标准库可用,需要利用kernel的一些函数,这些函数主要有: filp_open() filp_close(), vfs_read() vfs_write(),set_fs(),get_fs()等,这些函数在linux/fs.h和asm/uaccess.h头文件中声明。需要注意的是,在Linux kernel 4.9.0以上的版本,要使用vfs_read() vfs_write()进行读写,使用#if LINUX_VERSION_CODE >= KERNERL_VERSION(4,9,0)判断,包含linux/version.h
下面介绍主要步骤
1. 打开文件
filp_open()在kernel中可以打开文件,其原形如下:
strcut file* filp_open(const char* filename, int open_mode, int mode);
该函数返回strcut file*结构指针,供后继函数操作使用,该返回值用IS_ERR(2881064151)来检验其有效性。
参数说明
filename: 表明要打开或创建文件的名称(包括路径部分)。在内核中打开的文件时需要注意打开的时机,很容易出现需要打开文件的驱动很早就加载并打开文件,但需要打开的文件所在设备还不有挂载到文件系统中,而导致打开失败。
open_mode: 文件的打开方式,其取值与标准库中的open相应参数类似,可以取O_CREAT,O_RDWR,O_RDONLY等。
mode: 创建文件时使用,设置创建文件的读写权限,其它情况可以匆略设为0
2. 读写文件
kernel中文件的读写操作可以使用vfs_read()和vfs_write,在使用这两个函数前需要说明一下get_fs()和 set_fs()这两个函数。
vfs_read() vfs_write()两函数的原形如下:
ssize_t vfs_read(struct file* filp, char __user* buffer, size_t len, loff_t* pos);
ssize_t vfs_write(struct file* filp, const char __user* buffer, size_t len, loff_t* pos);
注意这两个函数的第二个参数buffer,前面都有__user修饰符,这就要求这两个buffer指针都应该指向用空的内存,如果对该参数传递kernel空间的指针,这两个函数都会返回失败-EFAULT。但在Kernel中,我们一般不容易生成用户空间的指针,或者不方便独立使用用户空间内存。要使这两个读写函数使用kernel空间的buffer指针也能正确工作,需要使用set_fs()函数或宏(set_fs()可能是宏定义),如果为函数,其原形如下:
void set_fs(mm_segment_t fs);
该函数的作用是改变kernel对内存地址检查的处理方式,其实该函数的参数fs只有两个取值:USER_DS,KERNEL_DS,分别代表用户空间和内核空间,默认情况下,kernel取值为USER_DS,即对用户空间地址检查并做变换。那么要在这种对内存地址做检查变换的函数中使用内核空间地址,就需要使用set_fs(KERNEL_DS)进行设置。get_fs()一般也可能是宏定义,它的作用是取得当前的设置,这两个函数的一般用法为:
mm_segment_t old_fs;
old_fs = get_fs();
set_fs(KERNEL_DS);
...... //与内存有关的操作
set_fs(old_fs);
还有一些其它的内核函数也有用__user修饰的参数,在kernel中需要用kernel空间的内存代替时,都可以使用类似办法。
使用vfs_read()和vfs_write()最后需要注意的一点是最后的参数loff_t * pos,pos所指向的值要初始化,表明从文件的什么地方开始读写。
3. 关闭读写文件
int filp_close(struct file*filp, fl_owner_t id);
该函数的使用很简单,第二个参数一般传递NULL值,也有用current->files作为实参的。
使用以上函数的其它注意点:
1. 其实Linux Kernel组成员不赞成在kernel中独立的读写文件(这样做可能会影响到策略和安全问题),对内核需要的文件内容,最好由应用层配合完成。
2. 在可加载的kernel module中使用这种方式读写文件可能使模块加载失败,原因是内核可能没有EXPORT你所需要的所有这些函数。
3. 分析以上某些函数的参数可以看出,这些函数的正确运行需要依赖于进程环境,因此,有些函数不能在中断的handle或Kernel中不属于任可进程的代码中执行,否则可能出现崩溃,要避免这种情况发生,可以在kernel中创建内核线程,将这些函数放在线程环境下执行(创建内核线程的方式请参数kernel_thread()函数)。
转载于:https://www.cnblogs.com/cbryge/p/6066978.html
例子这里有:https://blog.csdn.net/newnewman80/article/details/9363019
感谢!
内核驱动程序中如何读写user space的文件,方便调试程序的更多相关文章
- AR9331中Linux内核启动中与IRQ中断相关的文件
先列出框架,具体后继再来分析. 首先是lds文件,该文件设置了各个section在FLASH或RAM中的先后顺序. 位于~/openwrt1407/build_dir/target-mips_34kc ...
- 在Ubuntu上为Android系统内置C可执行程序测试Linux内核驱动程序(老罗学习笔记2)
在前一篇文章中,我们介绍了如何在Ubuntu上为Android系统编写Linux内核驱动程序.在这个名为hello的Linux内核驱动程序中,创建三个不同的文件节点来供用户空间访问,分别是传统的设备文 ...
- 为Android系统内置C可执行程序测试Linux内核驱动程序
在前一篇文章中,我们介绍了如何在Ubuntu上为Android系统编写Linux内核驱动程序.在这个名为hello的Linux内核驱动程序中, 创建三个不同的文件节点来供用户空间访问,分别是传统的设备 ...
- linux内核驱动中对文件的读写 【转】
本文转载自:http://blog.chinaunix.net/uid-13059007-id-5766941.html 有时候需要在Linux kernel--大多是在需要调试的驱动程序--中读写文 ...
- 【转】linux设备驱动程序中的阻塞机制
原文网址:http://www.cnblogs.com/geneil/archive/2011/12/04/2275272.html 阻塞与非阻塞是设备访问的两种方式.在写阻塞与非阻塞的驱动程序时,经 ...
- 在Ubuntu上为Android系统编写Linux内核驱动程序(老罗学习笔记1)
这里,我们不会为真实的硬件设备编写内核驱动程序.为了方便描述为Android系统编写内核驱动程序的过程,我们使用一个虚拟的硬件设备,这个设备只有一个4字节的寄存器,它可读可写.想起我们第一次学习程序语 ...
- 在Ubuntu上为Android增加硬件抽象层(HAL)模块访问Linux内核驱动程序(老罗学习笔记3)
简单来说,硬件驱动程序一方面分布在Linux内核中,另一方面分布在用户空间的硬件抽象层中.接着,在Ubuntu上为Android系统编写Linux内核驱动程序(老罗学习笔记1)一文中举例子说明了如何在 ...
- 在Ubuntu上为Android系统编写Linux内核驱动程序
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6568411 在智能手机时代,每个品牌的手机都有 ...
- 为Android增加硬件抽象层(HAL)模块访问Linux内核驱动程序
在Android硬件抽象层(HAL)概要介绍和学习计划一文中,我们简要介绍了在Android系统为为硬件编写驱动程序的方法.简单来说,硬件驱动程序一方面分布在Linux内核中,另一方面分布在用户空间的 ...
随机推荐
- 使用CMake生成解决方案后构建INSTALL报错
错误 1 error MSB3073: 命令“setlocal"D:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=Debug - ...
- React Native 开发环境搭建
1.安装 Python 2,不知道是否已支持 Python 3 2.安装 node,npm... 修改 npm 镜像,不建议使用 cnpm,cnpm 安装模块的路径与 npm 有差别 npm conf ...
- PymongoDB_study
import pymongo client = pymongo.MongoClient(host='localhost',port=27017)#连接数据库 #db = client.test#指定数 ...
- 查看python的OpenCV版本
安装"opencv" pip install opencv-python查看版本 import cv2 cv2.__version__
- 6_7_8_10html-css
Ps: 1.标准流 2.浮动 3.定位 CCS重点 <!DOCTYPE html> <html lang="en"> <head> & ...
- 使用密钥登录CentOS系统(基于密钥的认证)
在Window客户端有多种软件可以登陆ssh,比如putty,xshelll,secureCRT,我就以xshell为例设置使用公钥和私钥验证登陆服务器. 使用Xshell密钥认证机制远程登录Linu ...
- 使用Microsoft.Office.Interop.Excel.dll 文件来生成excel 文件
日常工作中经常需要将后台的数据导出成excel 格式,这里通过调用微软提供的类库来生成excel 文件. 具体是引用 了Microsoft.Office.Interop.Excel.dll 类库文件 ...
- logback.xml例子
我项目中一直使用这样的模板,留档,并纪念. <?xml version="1.0" encoding="UTF-8"?> <configura ...
- 20175227张雪莹 2018-2019-2 《Java程序设计》第九周学习总结
20175227张雪莹 2018-2019-2 <Java程序设计>第九周学习总结 教材学习内容总结 第十一章 JDBC数据库操作 MySQL数据库管理系统 下载安装MySQL 若下载的是 ...
- .net 多线程之async await
主线程遇到await 关键字后就交给子线程执行了 先定义一个task 可以让主线程和子线程同时执行,通过await关键字可以让主线程等待子线程执行完毕,await后面的代码可以视为异步方法的回调,可以 ...