几个内核函数:filp_open、filp_read、IS_ERR、ERR_PTR、PTR_ERR

本文介绍了在Linux内核态下如何进行文件操作,包括使用filp_open、vfs_read等函数的具体方法,以及如何在内核态正确处理内存地址,确保读写操作的正确性和安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 内核态文件操作

在用户态,我们操作文件可以用C库函数:open()、read()、write()等,但是在内核态没有库函数可用,这时就需要用内核的一些函数:filp_open、filp_close、vfs_read、vfs_write、

set_fs、get_fs等函数,在linux/fs.h和asm/uaccess.h中声明。

参数说明:

第一个参数表明要打开或创建文件的名称(包括路径部分)。

第二个参数文件的打开方式,其取值与标准库中的open相应参数类似,可以取O_CREAT,O_RDWR,O_RDONLY等。

第三个参数创建文件时使用,设置创建文件的读写权限,其它情况可以设为0

  该函数返回strcut file*结构指针,供后继函数操作使用,该返回值用IS_ERR()来检验其有效性。

参数说明:

第一个参数是filp_open返回的file结构体指针

第二个参数基本上都是NULL

参数说明:

第一个参数是filp_open返回的file结构体指针

第二个参数是buf,注意,这个参数有用__user修饰,表明buf指向用户空间的地址,如果传入内核空间的地址,就会报错,并返回-EFAULT,但在kernel中,要使这两个读写函数使用kernel空间的buf指针也能正确工作,需要使用set_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

下图是在内核中找到的一个场景:

第三个参数表明文件要读写的起始位置。

几点说明:(从网上查找的资料)

  1. Linux Kernel组成员不赞成在kernel中独立的读写文件(这样做可能会影响到策略和安全问题),对内核需要操作的文件内容,最好由应用层配合完成。
  2. 这些函数的正确运行需要依赖于进程环境,因此,有些函数不能在中断的handle或Kernel中不属于任何进程的代码中执行,否则可能出现崩溃,要避免这种情况发生,可以在kernel中创建内核线程,将这些函数放在线程环境下执行。

 

二.IS_ERR()、ERR_PTR()、PTR_ERR()小解

内核中的函数常常返回指针,问题是如果出错,也希望能够通过返回的指针体现出来。 总体来说,如果内核返回一个指针,那么有三种情况:合法指针,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相互转化的。

### OmegaConf 配置管理简介 OmegaConf 是一个强大的 Python 库,用于处理复杂的配置文件。它支持多种数据结构(如字典、列表)以及 YAML 文件的解析和操作。以下是有关如何使用 OmegaConf 的详细介绍。 #### 创建配置对象 可以通过 `OmegaConf.create` 方法创建一个新的配置对象。该方法可以接受字典、YAML 字符串或其他兼容的数据结构作为输入[^1]。 ```python import omegaconf from omegaconf import OmegaConf config_dict = {"database": {"host": "localhost", "port": 6379}} config = OmegaConf.create(config_dict) print(OmegaConf.to_yaml(config)) # 将配置转换为 YAML 格式的字符串 ``` #### 加载外部 YAML 文件 如果需要加载外部 YAML 文件,可使用 `OmegaConf.load` 方法。这使得程序能够轻松读取并应用存储在磁盘上的配置文件。 ```python yaml_file_path = "./example_config.yaml" file_conf = OmegaConf.load(yaml_file_path) # 打印加载后的配置内容 print(file_conf.database.host) # 输出 'localhost' ``` #### 合并多个配置源 当存在多个配置来源时(如默认设置与命令行参数),可以使用 `OmegaConf.merge` 来无缝合并它们。此功能允许开发者优先级较高的配置覆盖较低级别的配置项。 ```python default_configs = OmegaConf.create({"model": {"type": "resnet50"}}) cli_args = OmegaConf.from_dotlist(["model.type=vgg16"]) merged_config = OmegaConf.merge(default_configs, cli_args) assert merged_config.model.type == "vgg16" # 命令行参数成功覆盖默认值 ``` #### 动态更新配置 除了静态定义外,还可以通过访问器动态修改现有配置中的字段。这种灵活性非常适合运行时调整某些超参数或环境变量。 ```python dynamic_update = file_conf.copy() dynamic_update.database.port = 8080 print(dynamic_update.database.port) # 输出新的端口号 8080 ``` #### 错误处理机制 为了防止非法赋值破坏整个系统的稳定性,OmegaConf 提供了严格的模式控制选项。启用严格模式后,任何未声明过的键都将引发异常提示用户修正错误。 ```python strict_mode_enabled = file_conf.copy() strict_mode_enabled.set_struct(True) # 开启只读保护状态 try: strict_mode_enabled.new_field = True # 此处会抛出 AttributeError 异常 except AttributeError as e: print(f"Catch expected error: {e}") ``` --- ### 总结 以上展示了 OmegaConf 在不同场景下的典型用法,包括但不限于初始化配置实、加载外部资源、融合多层设定逻辑以及实施安全防护措施等方面的功能特性。希望这些子能帮助快速掌握其核心概念和技术要点!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值