fuse的direct_io

来源:互联网 发布:遥感数据预处理 编辑:程序博客网 时间:2024/05/16 18:18

direct_io:

      启用该选项后,fuse的kernel模块将不在内核的页缓存中为读写的文件保存缓存。文件的数据将从用户态的缓冲区和fuse daemon的缓冲区之间直接拷贝。fuse的direct_io选项fcntl里的O_DIRECT选项区别。两者本来是一个目的,都是要取消kernel里的页缓存。但是fuse实现的时候把这个功能的控制权交个了fuse文件系统的实现者,而不是访问fuse的用户进程。如果open一个fuse里的文件时采用了O_DRECT,那么fuse的内核模块会返回错误EINVAL。
       fuse的direct_io选项是在每次文件打开时由fuse的用户态daemon进程设置。daemon进程返回open的结果消息时会告诉kernel本次文件open之后是否采用direct_io方式。
fuse的daemon在实现时可以动态选择是否对本次文件读写采用direct_io(当时实际这样做的fuse系统估计没有,太复杂了)。
       direct_io既有优点也有缺点,看具体场景。对于大文件的顺序i/o,direct_io可以有效减少大量的内存拷贝。但是对于小文件的随机访问,不采用direct_io而保留kernel的page cache,在cache命令率较高的情况下可以有效的减少i/o的路径,减少用户进程跟fuse daemon的交互次数。
       fuse的direct_io技术实现细节很有意思。既然绕过了page cache,那么意味着文件的数据是从文件访问者的用户空间跟fuse daemon的用户空间直接做内存拷贝。实际这个拷贝的动作时fuse daemon做的。理论上说,现代OS不会允许一个进程直接访问另外一个进程的用户空间数据,除非共享内存之类的特殊情况。实际上fuse的daemon进程正式这样做的,当然fuse daemon只是是在内核态做的这件事情,安全性还是有保证的,从fuse daemon用户态代码并不能做任何违法的事情。direct_io的大致流程如下:
         用户进程调用sys_write一个fuse文件。
         用户进程陷入内核调用fuse_direct_write,进一步调用fuse_direct_io。
         fuse_direct_io获取用户进程buf的物理页的page指针和offset,并写入fuse的request消息。
         fuse daemon 读取/dev/fuse文件,陷入内核后调用fuse_dev_read,收到前面的request消息。最好在函数fuse_copy_fill,将请求消息中用户进程的物理页映射到fuse daemon。注意,这里做物理页映射的时候调用的是kmap_atomic。kmap_atomic是好处是不会导致整个tlb无效,是快速页映射。这样fuse daemon就可以直接访问另外一个进程的用户空间,做内存拷贝了。

原创粉丝点击