linux 内核函数 filp_open、filp_read、IS_ERR、ERR_PTR、PTR_ERR 简介
内核态文件操作
在用户态,我们操作文件可以用C库函数:open()、read()、write()等,但是在内核态没有库函数可用,这时就需要用内核的一些函数:filp_open、filp_close、vfs_read、vfs_write、set_fs、get_fs等函数,
在下列文件中声明:
/usr/lib/modules/3.10.0-514.el7.x86_64/build/include/linux/fs.h
/usr/lib/modules/3.10.0-514.el7.x86_64/build/include/asm-generic/uaccess.h
/usr/src/kernels/3.10.0-514.el7.x86_64/include/linux/err.h
extern struct file *filp_open(const char *, int, umode_t);
参数说明:
第一个参数表明要打开或创建文件的名称(包括路径部分)。
第二个参数文件的打开方式,其取值与标准库中的open相应参数类似,可以取O_CREAT,O_RDWR,O_RDONLY等。
第三个参数创建文件时使用,设置创建文件的读写权限,其它情况可以设为0
该函数返回strcut file*结构指针,供后继函数操作使用,该返回值用IS_ERR()来检验其有效性。
extern int filp_close(struct file *, fl_owner_t id);
参数说明:
第一个参数是filp_open返回的file结构体指针
第二个参数基本上都是NULL
extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *);
extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *);
参数说明:
第一个参数是filp_open返回的file结构体指针
第二个参数是buf,注意,这个参数有用__user修饰,表明buf指向用户空间的地址,如果传入内核空间的地址,就会报错,并返回-EFAULT,
但在kernel中,要使这两个读写函数使用kernel空间的buf指针也能正确工作,需要使用set_fs()
static inline void set_fs(mm_segment_t fs)
该函数的作用是改变kernel对内存地址检查的处理方式,
其实该函数的参数fs只有两个取值:USER_DS,KERNEL_DS,分别代表用户空间和内核空间,
默认情况下,kernel取值为USER_DS,即对用户空间地址检查并做变换。
那么要在这种对内存地址做检查变换的函数中使用内核空间地址,就需要使用set_fs(KERNEL_DS)进行设置,
它的作用是取得当前的设置,这两个函数的一般用法为:
filp_open()
mm_segment_t old_fs;
old_fs = get_fs();
set_fs(KERNEL_DS);
...... //与内存有关的操作
set_fs(old_fs);
filp_close
下图是在内核中找到的一个场景:
第三个参数表明文件要读写的起始位置。
几点说明:(从网上查找的资料)
Linux Kernel组成员不赞成在kernel中独立的读写文件(这样做可能会影响到策略和安全问题),对内核需要操作的文件内容,最好由应用层配合完成。
这些函数的正确运行需要依赖于进程环境,因此,有些函数不能在中断的handle或Kernel中不属于任何进程的代码中执行,否则可能出现崩溃,要避免这种情况发生,可以在kernel中创建内核线程,将这些函数放在线程环境下执行。
#ifndef _LINUX_ERR_H
#define _LINUX_ERR_H#include <linux/compiler.h>#include <asm/errno.h>/** Kernel pointers have redundant information, so we can use a* scheme where we can return either an error code or a dentry* pointer with the same return value.** This should be a per-architecture thing, to allow different* error and pointer decisions.*/
#define MAX_ERRNO 4095#ifndef __ASSEMBLY__#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)static inline void * __must_check ERR_PTR(long error)
{return (void *) error;
}static inline long __must_check PTR_ERR(const void *ptr)
{return (long) ptr;
}static inline long __must_check IS_ERR(const void *ptr)
{return IS_ERR_VALUE((unsigned long)ptr);
}static inline long __must_check IS_ERR_OR_NULL(const void *ptr)
{return !ptr || IS_ERR_VALUE((unsigned long)ptr);
}
内核中的函数常常返回指针,问题是如果出错,也希望能够通过返回的指针体现出来。
总体来说,如果内核返回一个指针,那么有三种情况:合法指针,NULL指针和非法指针。
在linux中有很多错误,内核错误可以参考include/asm-generic/errno-base.h。
MAX_ERRNO定义了最大的错误号4095,刚好是4k-1,所以内核地址保留了0xfffffffffffff000~0xffffffffffffffff(64位系统)用来记录错误号,也就是说这段地址和Linux的错误号是一一对应的,可以用上面的内联函数相互转化。
比如说我们上面的filp_open函数返回值,用IS_ERR函数去检查,如果地址落在0xfffffffffffff000~0xffffffffffffffff范围,
表示filp_open函数失败,IS_ERR为1,同时filp_open返回的错误地址对应一个linux的错误号,
如果想知道是哪个错误号,就用PTR_ERR函数来转化。
错误的返回地址和错误号是可以使用 ERR_PTR、PTR_ERR 相互转化的。
linux 内核函数 filp_open、filp_read、IS_ERR、ERR_PTR、PTR_ERR 简介相关推荐
- linux内核函数出错的返回值
linux内核函数出错的返回值 1. 函数返回指针 2. 如何通过错误信息指针来返回错误信息 3. 出错代码返回指针在(-1000,0)区间 4. 错误的判断和错误原因的打印 4.1 错误的判断 4. ...
- linux应用调用内核函数,Hooking linux内核函数(一):寻找完美解决方案
前言 我们最近参与了一个Linux系统安全相关项目,需要hooking几个重要的Linux内核函数调用,例如打开文件和启动进程,并利用它来启用系统活动监控并抢先阻止可疑进程. 最后,我们发明了一种有效 ...
- 如何替换一个Linux内核函数的实现-热补丁原理
昨晚发过誓了.不会再接着写二进制hook的手艺了,今天有网友咨询技术细节,终于又忍不住了- 为了不违背即便是胡乱说出口誓言,今天不写二进制hook,今天用C语言写,二进制只是沾点边儿! 看题目, 替换 ...
- linux 内核函数 copy_from_user和copy_to_user 介绍
前言 copy_from_user和copy_to_user这两个函数相信做内核开发的人都非常熟悉,分别是将用户空间的数据拷贝到内核空间以及将内核空间中的数据拷贝到用户空间.这两个函数一般用于系统调用 ...
- linux内核函数open源码,open()在Linux内核的实现(1)-基本实现
原标题:open()在Linux内核的实现(1)-基本实现 1.基本说明 在用户态使用open()时,必须向该函数传入文件路径和打开权限.这两个参数传入内核后,内核首先检查这个文件路径存在的合法性,同 ...
- linux内核函数 ffs,linux内核中的宏ffs(x)【转】
linux内核中ffs(x)宏是平台相关的宏,在arm平台,该宏定义在 arch/arm/include/asm/bitops.h #define ffs(x) ({ unsigned long __ ...
- linux内核函数 ffs,linux内核中的宏ffs(x)
转自:https://www.cnblogs.com/fengeryi/p/3449720.html linux内核中ffs(x)宏是平台相关的宏,在arm平台,该宏定义在 arch/arm/incl ...
- linux内核函数kmalloc,Linux内核内存分配函数之devm_kmalloc和devm_kzalloc
本文介绍Linux内核内存分配函数devm_kmalloc()和devm_kzalloc(). 一.devm_kmalloc 文件:drivers/base/devres.c,定义如下: /** * ...
- 嵌入式烧写Linux内核,嵌入式linux 内核和根文件系统烧写方式简介
总体来说,嵌入式Linux内核和根文件的引导与PC机差不多. 嵌入式linux内核和根文件系统可以存放在各种可能的存储设备中,一般情况下我们将内核和根文件系统直接烧入到Flash中(包括NOR和NAN ...
- linux内核函数kmalloc,Linux_Linux平台上几个常见内核内存分配函数,* kmallocPrototype:#incl - phpStudy...
Linux平台上几个常见内核内存分配函数 * kmalloc Prototype: #include void *kmalloc(size_t size, int flags); Kmalloc分配一 ...
最新文章
- 【剑指offer-Java版】28字符串的排列
- UVa10825 Anagram and Multiplication(dfs)
- ack机制之代码实现,实现BaseRichBolt的方式,使用BaseBasicBolt的方式实现BaseRichBolt发ack和fail的功能
- Apache 的 httpd.conf 详解(很实用)
- Julia: 为什么要设计nothing
- 魔鬼训练Day2作业
- 保研之路——中山大学数据科学与计算机学院直硕夏令营
- AirPlay、AirTunes 移植开发
- 基于c语言图书管理系统设计与开发,基于C语言图书管理系统设计与实现.doc
- 软件架构师的12项修炼[2]——关系技能修炼(2)——领导力、政治
- 主机名、域名、 IP地址之间的关系
- [2019/12]饮水姑苏,止于至善
- 实现multi()函数,参数个数不限,返回所有参数的乘积
- OpenCV:02基础知识和绘制图形
- TensorRT加速
- 为什么人到中年就危机了呢?
- Servlet API中forward()与redirect()的区别?
- 苹果 iphone降级
- javac, java非标准参数说明
- 区块链能保护隐私?别被忽悠了