深入解析FUSE源码:Linux内核与用户空间的交互

版权申诉
0 下载量 111 浏览量 更新于2024-08-18 收藏 316KB DOCX 举报
"本文档是对FUSE-2.9.2源码的深入学习和总结,主要探讨了在Linux内核中FUSE实现的文件系统操作,特别是write操作的流程,并介绍了关键的数据结构。文档首先概述了基于FUSE的用户空间文件系统执行write操作的基本步骤,然后详细分析了FUSE模块加载、mount和open过程,以及文件write的具体实现。此外,还提到了FUSE中的重要数据结构,但并未涉及所有细节,仅列举了与讨论相关的关键部分。" 在Linux中,FUSE(Filesystem in Userspace)允许开发者在用户空间实现文件系统,降低了编写文件系统的门槛。FUSE源码的分析主要围绕write操作展开,这是文件系统中最常见的操作之一。当客户端在挂载的FUSE目录下对一个常规文件调用write时,write操作在用户空间启动。这个操作会通过虚拟文件系统(VFS)的接口vfs_write进行,进而调用fuse_file_aio_write,将写请求放入FUSE连接的request pending queue。 此时,用户空间的libfuse守护进程通过fuse_session_loop不断轮询/dev/fuse设备,一旦检测到request queue有新请求,就会通过fuse_kern_chan_receive接收。接收过程中,数据会被读取并传递给用户定义的write操作处理。处理完成后,状态通过fuse_reply_write返回内核,再次调用VFS的vfs_write接口,最后将结果通过fuse_dev_write送回原始发起write请求的进程,完成整个write操作。 在数据结构方面,文档提到了FUSE连接(fuse_connection),它管理着pending list、processing list和io lists等,这些列表用于跟踪和处理来自用户空间的请求。然而,文档并未详细展示所有数据结构的完整细节,仅列举了与讨论相关的关键部分。 尽管文档没有涵盖所有内核同步和异常检查等复杂内容,但它为理解FUSE如何在用户空间和内核之间协调文件系统操作提供了基础。这对于理解和开发基于FUSE的自定义文件系统非常有帮助,特别是对于那些需要深入了解Linux内核和文件系统交互的"事业编"专业人士来说,是一份有价值的参考资料。

解释每一句class RepVggBlock(nn.Layer): def init(self, ch_in, ch_out, act='relu', alpha=False): super(RepVggBlock, self).init() self.ch_in = ch_in self.ch_out = ch_out self.conv1 = ConvBNLayer( ch_in, ch_out, 3, stride=1, padding=1, act=None) self.conv2 = ConvBNLayer( ch_in, ch_out, 1, stride=1, padding=0, act=None) self.act = get_act_fn(act) if act is None or isinstance(act, ( str, dict)) else act if alpha: self.alpha = self.create_parameter( shape=[1], attr=ParamAttr(initializer=Constant(value=1.)), dtype="float32") else: self.alpha = None def forward(self, x): if hasattr(self, 'conv'): y = self.conv(x) else: if self.alpha: y = self.conv1(x) + self.alpha * self.conv2(x) else: y = self.conv1(x) + self.conv2(x) y = self.act(y) return y def convert_to_deploy(self): if not hasattr(self, 'conv'): self.conv = nn.Conv2D( in_channels=self.ch_in, out_channels=self.ch_out, kernel_size=3, stride=1, padding=1, groups=1) kernel, bias = self.get_equivalent_kernel_bias() self.conv.weight.set_value(kernel) self.conv.bias.set_value(bias) self.delattr('conv1') self.delattr('conv2') def get_equivalent_kernel_bias(self): kernel3x3, bias3x3 = self._fuse_bn_tensor(self.conv1) kernel1x1, bias1x1 = self._fuse_bn_tensor(self.conv2) if self.alpha: return kernel3x3 + self.alpha * self._pad_1x1_to_3x3_tensor( kernel1x1), bias3x3 + self.alpha * bias1x1 else: return kernel3x3 + self._pad_1x1_to_3x3_tensor( kernel1x1), bias3x3 + bias1x1 def _pad_1x1_to_3x3_tensor(self, kernel1x1): if kernel1x1 is None: return 0 else: return nn.functional.pad(kernel1x1, [1, 1, 1, 1]) def _fuse_bn_tensor(self, branch): if branch is None: return 0, 0 kernel = branch.conv.weight running_mean = branch.bn._mean running_var = branch.bn._variance gamma = branch.bn.weight beta = branch.bn.bias eps = branch.bn._epsilon std = (running_var + eps).sqrt() t = (gamma / std).reshape((-1, 1, 1, 1)) return kernel * t, beta - running_mean * gamma / std

2023-05-15 上传