内核态文件操作【转】
转自:http://blog.csdn.net/yf210yf/article/details/8997007
有时候需要在Linux kernel--大多是在需要调试的驱动程序--中读写文件数据。在kernel中操作文件没有标准库可用,需要利用kernel的一些函数,这些函数主 要有: filp_open() filp_close(), vfs_read() vfs_write(),set_fs(),get_fs()等,这些函数在linux/fs.h和asm/uaccess.h头文件中声明。下面介绍主 要步骤
1. 打开文件
filp_open()在kernel中可以打开文件,其原形如下:
strcut file* filp_open(const char* filename, int open_mode, int mode);
该函数返回strcut file*结构指针,供后继函数操作使用,该返回值用IS_ERR()来检验其有效性。
参数说明
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()函数)。
=========================================================================================
转载于: http://blogold.chinaunix.net/u3/113927/showart_2495807.html
在VFS的支持下,用户态进程读写 任何类型的文件系统都可以使用read和write着两个系统调用,但是在linux内核中没有这样的系统调用我们如何操作文件呢?我们知道read和 write在进入内核态之后,实际执行的是sys_read和sys_write,但是查看内核源代码,发现这些操作文件的函数都没有导出(使用 EXPORT_SYMBOL导出),也就是说在内核模块中是不能使用的,那如何是好?
通过查看sys_open的源码我 们发现,其主要使用了do_filp_open()函数,该函数在fs/namei.c中,而在改文件中,filp_open函数也是调用了 do_filp_open函数,并且接口和sys_open函数极为相似,调用参数也和sys_open一样,并且使用EXPORT_SYMBOL导出 了,所以我们猜想该函数可以打开文件,功能和open一样。使用同样的查找方法,我们找出了一组在内核中操作文件的函数,如下:
功能 函数原型
打开文件 struct file *filp_open(const char *filename, int flags, int mode)
读取文件 ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
写文件 ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
关闭文件 int filp_close(struct file *filp, fl_owner_t id)
我们注意到在vfs_read和vfs_write函数中,其参数buf指向的用户空间的内存地址,如果我们直接使用内核空间的指针,则会返回-EFALUT。所以我们需要使用
set_fs()和get_fs()宏来改变内核对内存地址检查的处理方式,所以在内核空间对文件的读写流程为:
mm_segment_t fs = get_fs();
set_fs(KERNEL_FS);
//vfs_write();
vfs_read();
set_fs(fs);
下面为一个在内核中对文件操作的例子:
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/fs.h>
- #include <linux/uaccess.h>
- static char buf[] = "你好";
- static char buf1[10];
- int __init hello_init(void)
- {
- struct file *fp;
- mm_segment_t fs;
- loff_t pos;
- printk("hello enter\n");
- fp = filp_open("/home/niutao/kernel_file", O_RDWR | O_CREAT, 0644);
- if (IS_ERR(fp)) {
- printk("create file error\n");
- return -1;
- }
- fs = get_fs();
- set_fs(KERNEL_DS);
- pos = 0;
- vfs_write(fp, buf, sizeof(buf), &pos);
- pos = 0;
- vfs_read(fp, buf1, sizeof(buf), &pos);
- printk("read: %s\n", buf1);
- filp_close(fp, NULL);
- set_fs(fs);
- return 0;
- }
- void __exit hello_exit(void)
- {
- printk("hello exit\n");
- }
- module_init(hello_init);
- module_exit(hello_exit);
- MODULE_LICENSE("GPL");
另:
inux内核态用不到c函数库的,所以写文件是一个比较费事的事情。
下面这段代码,接我上一篇,是重构linux语义用到的,功能为获取一些结构体元素的偏移。
写文件的主体代码如下
01
|
static void filewrite( char * filename, char * data)
|
02
|
{
|
03
|
struct file *filp;
|
04
|
mm_segment_t fs;
|
05
|
filp = filp_open(filename, O_RDWR| O_APPEND| O_CREAT, 0644);
|
06
|
if (IS_ERR(filp))
|
07
|
{
|
08
|
printk( "open error...\n" );
|
09
|
return ;
|
10
|
}
|
11
|
fs=get_fs();
|
12
|
set_fs(KERNEL_DS);
|
13
|
filp->f_op->write(filp, data, strlen (data),&filp->f_pos);
|
14
|
set_fs(fs);
|
15
|
filp_close(filp,NULL);
|
16
|
}
|
转载于:https://www.cnblogs.com/sky-heaven/p/5549357.html
内核态文件操作【转】相关推荐
- 用户态与内核态 文件流与文件描述符 简介【转】
转自:https://www.cnblogs.com/Jimmy1988/p/7479856.html 用户态和内核态 程序代码的依赖和调用关系如下图所示: Lib:标准ASCI C函数,几乎所有的平 ...
- Linux 的内核态与用户态
我们常说的 Linux 严格来说指代的是 Linux Kernel,泛指使用或裁剪标准 Linux Kernel 并在此基础之上实现各种应用程序解决方案的操作系统发行版本(e.g. RHEL.SUSE ...
- 用户态和内核态之间的切换
用户态和内核态之间的切换 切换方式 从用户态到内核态切换可以通过三种方式,或者说会导致从用户态切换到内核态的操作: 系统调用,这个上面已经讲解过了,在我公众号之前的文章也有讲解过.其实系统调用本身就是 ...
- 理解用户态切换到内核态——内核态下有一个特殊的进程
现在想想,从用户态进入到内核态,相当于一次进程切换--这就好像内核态下有一个特殊的进程. 我就把进入内核态后,理解为进入了一个特殊的进程,一切都忽然合理了,恍然大悟--所以所有用户态的task(称之为 ...
- ioctrl原形 linux_Linux常见的几种用户态与内核态交互方式优缺点
背景 由于Linux 系统分为了用户态和内核态,用户态在设计初衷就是运行与硬件无关的应用程序,与硬件相关的操作大部分都集中在内核态处理.所以用户态如果需要获取硬件信息,或者操作硬件,必须要通过某种方式 ...
- 「操作系统」什么是用户态和内核态?为什么要区分
「操作系统」什么是用户态和内核态?为什么要区分 参考&鸣谢 从根上理解用户态与内核态 程序员阿星 并发编程(二十六)内核态和用户态 Lovely小猫 操作系统之内核态与用户态 fimm 文章目 ...
- 用户态和内核态的简单理解
文章目录 linux基础 系统调用和库函数的区别 为什么要区分用户态和内核态? 用户态和内核态的切换耗费时间的原因 哪些情况会出出现用户态和内核态的切换 用户态切换到内核态的三种方式 linux基础 ...
- 从根上理解用户态与内核态
欢迎来到操作系统系列,采用图解 + 大白话的形式来讲解,让小白也能看懂,帮助大家快速科普入门. 本篇文章开始探秘用户态与内核态,虽然一般面试不会问这个,但搞清楚这块,对我们理解整个计算机系统是及其有意 ...
- 计算机内核态和用户态,用户态和内核态的区别是什么
用户态和内核态的区别是,内核态运行操作系统程序,操作硬件,用户态运行用户程序:当程序运行在3级特权级上时,可以称之为运行在用户态,当程序运行在0级特权级上时,称之为运行在内核态. 本文操作环境:win ...
最新文章
- SQL 时间类型转字符串格式列表
- 怎样将项目上传到github上
- matlab apfc,APFC-Boost 带APFC的Boost升压变换器在Matlab中的仿真实现 - 下载 - 搜珍网...
- 2020-11-15(getinstance)
- 利用poi进行数据的excel导出
- http的302,303和307
- 一个配件、一块面料,制造企业流水线因为AI变了新模样(人工智能应用案例)
- 局域网只能看到一部分电脑_win10 网上邻居看不到其它电脑、共享不了文件
- 前端学习(172):格式化文本
- Linux基础提高_系统性能相关命令
- 自适应网页设计(Responsive Web Design)响应式设计
- python函数介绍
- 红橙Darren视频笔记 缓存方案 缓存到数据库(数据库操作) 上
- tcp关闭连接:挥手讨论
- 阿里云oss权限控制,上传下载测试
- 深度学习中常用优化器算法Optimizer详解(BGD、SGD、MBGD、Momentum、NAG、Adagrad、Adadelta、RMSprop、Adam)
- sqlserver 2008完整安装教程
- 线性代数之 实对称矩阵,正交对角化,二次型与正定矩阵
- 百度地图Android开发清除上一次驾车导航路线
- java模拟人生世界冒险_《模拟人生3世界冒险》的冒险心得与注意点
热门文章
- SQL定时自动备份,并将备份文件加密压缩并自动下载的实现
- 时态数据库的应用介绍(1)
- 可视化管理一目了然 锐捷RG-UAC承载荔湾教育局“御网”之道
- 《Android开发秘籍(第2版)》——第1.4节Android设备间的硬件差异
- HA集群--corosync+pacemaker
- C++与tolua++的完整调用流程,超级详解解决交互疑难
- 【c++模板实现】二叉查找树
- CS 客户端不引用AE
- sql 包含某个字符_「17」MySQL中正则表达式查询的SQL语句集锦
- java 快排_秋招|字节跳动Java后台已上岸,发个面经回馈牛油