在用户空间编写文件系统驱动程序比在内核空间编写更容易?

我将以Linux NTFS驱动程序为例。

Linux内核的NTFS驱动程序在内核中只有非常有限的写入支持,5年后仍被认为是实验性的。

相同的开发团队创build了ntfsmount用户空间驱动程序,它具有几乎完美的写入支持。

同样,由不同团队编写的NTFS-3G项目也有近乎完美的写作支持。

为什么内核驱动器需要更长的时间? 发展更难吗?

说已经存在一个体面的用户空间应用程序不是内核驱动程序不强制的原因。

注意:不要将其迁移到superuser.com。 从编程的angular度来看,我想要一个编程沉重的答案,而不是一个实际的使用答案。 如果这个问题不适合SO,请告诉我为什么我可以编辑它。

我不知道NTFS linux驱动程序开发的内幕,但我可以想象一些使用户空间开发速度比内核空间快的事情:

  • 更简单的API – 用户级库提供的更高级别的抽象(例如内存管理)肯定会简化开发
  • 更容易的调试 – 比调试内核更容易调试用户空间进程
  • 进程隔离 – 这是我要说的一件事是负责在用户空间中更快的开发。 您的用户空间文件系统驱动程序做坏事会导致,在最坏的情况下,在一个损坏的文件系统和您的驱动程序进程死亡,而在内核空间可能会导致一个完整的系统崩溃。 这会导致更快的调试周期,从而导致整个错误的处理速度越来越快。

需要注意的是,特别是在Linux下, 实验可能也意味着“某人在这里倾倒的代码,这在当时看起来可以接受但可能不会被主动维护”。

我是在用户空间保留文件系统的忠实粉丝,但我也应该指出,我是一个大型的微内核爱好者 。 我觉得这是可行的,最好保留文件系统在用户空间,原因如下:

用户空间文件系统更容易维护

花点时间看看ext3cow文件系统 ,一个PHD项目,在很短的时间内获得了相当大的牵引力。 它的作者毕业,然后转到职业生涯,很少有时间在文件系统上工作。 因为它不在树上,所以Linux之间不断变化的内部需要任何人都想在现代内核上使用它,以获得不太多的知识。

如果使用FUSE API,维护将变得更加容易,而将ext3转换为写入文件系统上的副本的实际工作将得到更多的曝光。 这也涉及到正在收集模型的内核代码,因为没有人足够勇敢(或厌倦)触摸它。

用户空间文件系统更容易调试

在用户空间中,你有很棒的工具,比如Valgrind(和它的朋友,如地块),这些工具是非常有用的工具,而且易于使用。 与内核调试相关的学习曲线对于许多人来说只是跳入其中并进行编码而言通常太大了。 请注意,我正在清楚地分离FUSE和微内核体系结构,正如在这个答案中指出的那样。 一些基于微内核的系统非常难以调试,主要是由于运行服务(vfs,块设备,文件系统,ipc)之间的通信竞争。 在这两种情况下,代码都比较容易调试,因为它不在内核之中,只要将它从内核中移出就不会引入奇怪的复杂性。

在任何情况下,我都会把GDB和Valgrind用在任何一天的嘈杂的printk()调试中,或者试图从Linux中相当隐蔽的内核调试挂钩中理解。 我也将享受使用我选择的任何调试(甚至垃圾收集 ) malloc()实现的能力。 只要与FUSE一起工作,我的C库也是一样的。 我不是在嘲弄Linux的内核库,但是我喜欢我的生物的舒适感。

用户空间文件系统更易于使用

对于贫困的用户来说,安装和维护他们想要使用的任何文件系统都是一个很大的好处,但这实际上是最终的游戏。 如果你的文件系统不在内核之中,它可以独立于内核前进,这意味着用户可以根据你的发布周期进行升级。 你可以想象,在Linux发展到下一个候选版本的时候,可以达到6个里程碑版本。 这也使得发行版和OEM厂商能够在你的FS得到比它是内核模块所需要的测试快得多的测试的时候获得FS。

Norman Ramsey 已经将与文件系统相关的可靠性因素描述为微内核架构中的服务。 然而,可靠性意味着不需要一个倾向于隐藏(或推迟)错误和其他问题的转世服务。 我同意这样的观点,即如果失败的根挂载不会引起内核中止,那么这也是可能的,但对于启用FUSE的单片内核也是如此。

总之,编写一个文件系统已经够用了,而不必处理内核空间的运行。 我宁愿使用FUSE API,或者在基于微内核的操作系统中研究IPC / VFS服务实现,而不是将其作为内核模块编写。

内核代码必须比用户模式代码更高的安全性和安全性(即无缺陷)标准。

用户空间中有更多的好东西可用,所以开发软件更容易。 如果文件系统在用户空间中,那么文件系统中的一个错误就很难把整个内核关闭。

在Mach和Windows NT这样的项目中,这个原则被认为是极端的,在这个项目中,系统被设计成一个微内核 ,尽可能多的服务被放置在用户空间中。