一种基于系统调用拦截技术的用户态文件系统性能优化方法与流程
- 国知局
- 2024-08-22 15:01:37
本发明涉及一种优化方法,具体涉及一种基于系统调用拦截技术的用户态文件系统性能优化方法,属于计算机存储。
背景技术:
1、经典操作系统存储io(input and output)体系架构主要采用内核文件系统技术,即自上而下依次为用户态的文件系统接口fs(filesystem interface)、内核态的虚拟文件系统vfs(virtual file system)和文件系统实现层fsi(filesystem impl)。其中fi提供了面向posix的语义支持能力,通过触发系统调用(system call)来将io请求路由到内核;io请求进入内核之后,vfs提供了通用的文件系统接口和抽象层,使得io请求可以透明地路由至不同类型的文件系统实现层fsi;而fsi向vfs提供完整的节点、目录以及文件操作等功能函数,涉及inode_operations,file_operations,dentry_operations等。上述流程可参考图1中黑虚线部分示意;图1为内核态与用户态文件系统流程对比示意图
2、此经典的内核态存储io体系架构存在诸多问题,归纳总结如下:
3、1)从健壮性角度而言,内核态文件系统的影响范围大,一旦发生故障,整个os环境都会受到影响;假如文件系统在用户态部署,受影响的仅是服务进程本身;
4、2)从便捷性角度而言,每次内核态功能部件的变更均需重启整个os环境,对上层应用的影响范围大;
5、3)从效益比角度而言,使用c语言开发和调试内核态文件系统效率低下且难度高;不同的os环境甚至不同的内核版本差异性都可能带来兼容问题。
6、鉴于在内核态下开发文件系统不仅难度高,而且不易调试,一旦出问题便导致系统崩溃的问题。用户态文件系统(fuse)将文件系统的实现代码迁移至用户态空间,fusedriver在用户态空间和内核空间之间通过虚拟设备文件(/dev/fuse)建立了一个桥梁,使得用户自定义的文件系统(fuse system impl)与标准文件系统接口(vfs)完成通信,最终通过原生存储路径(native storage path)进入内核态去访问物理存介质驱动(例如ext4、xfs等)或者网络介质(例如ceph、hdfs)完成数据落盘。上述流程可参考图1中黑实线部分示意;
7、fuse优势特点在于允许非特权用户创建自己的文件系统而无需编辑内核代码;同时保持应用接口层面不发生变化,io请求依然通过系统调用进入内核。因此,fuse在降低开发调试复杂度和提高系统稳定性方面优势明显。
8、但是,fuse的io处理链路比内核态文件系统增加了两次上下文切换,继而导致两次不必要的数据拷贝开销;因此,fuse整体性能表现劣于内核态文件系统。在读写大文件或者随机读写的场景下,频繁的内核态与用户态之间的切换将会消耗大量的系统资源,进而导致读写效率降低。因此,迫切的需要一种新的方案解决该技术问题。
技术实现思路
1、本发明正是针对现有技术中存在的技术问题,提供一种基于系统调用拦截技术的用户态文件系统性能优化方法,本发明借助syscall intercept技术和preload机制,在核心基础库动态库glibc载入内存之前,对其text代码段做反编译处理,将系统调用syscall相关的指令替换成用户态自定义文件操作抽象接口(file operation entry),之后通过系统环境变量ld_preload引导应用进程访问file operation entry,从而让原本应该路由到内核态的io请求保持在用户态被处理(所述发明概要可参考图2中黑实线部分示意)。因此,本发明彻底解决了用户态与内核态之间两次切换导致的性能问题;其不仅保持了北向文件系统在接口层面的兼容性,使得上层应用对底层文件系统迭代所带来的变化无感知,而且进一步降低了用户态文件系统(fuse)的调测难度。
2、为了实现上述目的,本发明的技术方案如下,一种基于系统调用拦截技术的用户态文件系统性能优化方法,所述优化方法包括以下步骤:
3、步骤1:标准系统调用与中断拦截并生成自定义系统调用拦截库,
4、步骤2:自定义系统调用拦截库注入与运行时替换,
5、步骤3:系统调用与io请求映射,
6、步骤4:fuse_operations抽象接口与用户自定义api映射,
7、步骤5:拦截库卸载与状态恢复。
8、其中,
9、步骤1:标准系统调用与中断拦截并生成自定义系统调用拦截库,具体如下:
10、通常glibc按照固定规则对系统调用syscall进行封装操作,寄存器eax传递系统调用号,系统调用号用来确定系统调用。寄存器ebx,ecx,edx,esi,edi,ebp依次传递系统调用参数。参数个数决定设置寄存器的个数。执行int0x80指令切入内核执行系统调用;
11、本方法结合核心基础库glibc的源码并且对其动态二进制进行反编译处理,通过替换syscall指令达到文件系统调用的拦截的目的,具体步骤如下:
12、11)识别并定位与文件系统相关的系统调用syscall指令信息(地址、编号等)或中断int;
13、12)通过反向转换映射系统调用号即可获得系统调用名称、参数类型、参数个数以及返回值类型;
14、13)将glibc中涉及到的文件系统调用syscall与文件操作调用入口(fileoperation entry)一一映射(下表仅罗列部分api);之后将文件操作调用入口(fileoperation entry)的二进制代码地址以hook形式插入到glibc中目标syscall指令的地址处,替换原有的系统调用指令;修改成完成后,将其保存为自定义系统调用拦截库(user-glibc)。
15、步骤2:自定义系统调用拦截库注入与运行时替换,具体如下:
16、通过系统环境变量ld_preload加载自定义系统调用拦截库(user-glibc)到指定用户态进程环境,实现对系统调用的拦截和替换功能。具体步骤可细分为:21)重新声明系统环境变量ld_preload,引导用户态进程加载自定义系统调用拦截库;22)用户态进程运行时,通过自定义系统调用拦截库中的符号表调用13)中以hook形式插入的文件操作调用入口(file operation entry);
17、步骤3:系统调用与io请求映射,具体如下:
18、通常当用户态进程通过glibc执行系统调用时,vfs会将这些操作发送至fusedriver,fuse driver创建一个io request并发送至请求队列中,等待libfuse处理;在此期间,用户进程处于阻塞状态。
19、本方法使用用户态fuse daemon替换内核态的fuse driver,通过共享内存机制完成系统调用到io request的映射;具体步骤可细分为:
20、31)采用用户态fuse daemon进程替换掉内核态fuse driver内核模块;
21、32)使用共享内存(shared memory)替换掉虚拟设备文件/dev/fuse;
22、33)在用户态fuse daemon进程内仿照fuse driver模块执行io request的创建、传递、状态维护;即在文件操作调用入口(file operation entry)的函数内通过等子函数功能将文件操作转换为io request后投入共享内存区域内。
23、步骤4:fuse_operations抽象接口与用户自定义api映射,具体如下,
24、通常libfuse通过读取/dev/fuse将io request从内核队列中取出,并且通过fuse_operations抽象接口对接用户自定义函数实现完成io处理,当处理完请求后,libfuse会将reply写回/dev/fuse,fuse driver此时把request标记为completed,最终唤醒用户进程。
25、本方法中libfuse通过shm_open()接口获取32)中已声明的共享内存句柄,并从其中读取io request,之后通过io请求号等信息借助fuse_operations抽象接口访问用户自定义的io函数实现,最终完成io处理。当处理完请求后,libfuse会将reply写回共享内存,fuse daemon此时把request标记为completed,最终唤醒用户进程。
26、其中,fuse_operations屏蔽了底层的相关对象,直接以文件名作为参数,用户在使用之前根据需要重载定义操作接口函数;
27、步骤5:拦截库卸载与状态恢复,应用退出时,卸载系统调用拦截库并恢复系统调用表的原始状态。
28、相对于现有技术,本发明具有如下优点,
29、1)该技术方案将系统调用与中断拦截在用户态处理,解决了用户态与内核态之间两次切换导致的性能问题;
30、2)该技术方案将内核态的io处理路径迁移至用户态处理,不仅规避了内核奔溃带来的风险,而且进一步降低了用户态文件系统(fuse)的开发和测试难度;
31、3)该技术方案保持了北向文件系统在接口层面的兼容性,使得上层应用对底层文件系统迭代所带来的变化无感知,老旧应用无序二次开发即可平稳运行。
本文地址:https://www.jishuxx.com/zhuanli/20240822/280825.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 YYfuon@163.com 举报,一经查实,本站将立刻删除。
下一篇
返回列表