【问题标题】:how to find a loop in the file system?如何在文件系统中找到循环?
【发布时间】:2009-03-22 19:28:33
【问题描述】:

如何在 Linux 的文件系统中找到循环?我正在索引所有文件以使搜索快速(O(1))......我正在使用c编程语言通过使用dir.h中的库函数来实现......我可以扫描整个文件系统但它进入如果文件系统中存在循环,则为循环(示例循环挂载)...如何在文件系统中找到循环..当文件系统中存在循环时,我已经看到 updatedb 命令报告...我不明白逻辑...任何人都可以帮助找到解决方案吗?

【问题讨论】:

  • 堆栈溢出对新用户有点不友好。当投票反对某人时,请留下评论,解释你为什么这样做,并暗示他们应该做些什么来让它变得更好。

标签: c linux


【解决方案1】:

防止重新扫描图中节点的一般方法是在传递节点时对其进行标记,然后忽略已标记的节点。如果您不想修改正在扫描的图形,这不是非常实用,因此您需要一种在外部标记节点的方法。我能想到的在 linux 下执行此操作的最简单方法是为您访问的每个目录存储一个设备/inode。然后,当您查看目录时,首先检查您是否还没有看到任何具有相同设备/inode 的目录。这不仅可以处理循环,还可以处理相互合并的树。

要获取设备/inode 编号,请查看 stat/fstat 函数以及 stat 结构的 st_dev 和 st_ino 成员。

对于存储数据,您可能希望查看hash-table 或二叉树。

【讨论】:

    【解决方案2】:

    顺便说一句。您不需要在文件系统中搜索循环。

    您正在索引整个磁盘。因此,您不需要遵循符号链接,因为每个文件都必须能够以正常方式访问(没有符号链接)。如果某个磁盘被多次挂载,您只需要检查挂载点,而忽略其他挂载点。

    【讨论】:

      【解决方案3】:

      我在这里发现了一条关于 finding loops in a DAG 的有趣评论:

      Steinar H. Gunderson 写道:

      2004 年 2 月 26 日星期四 00:28:32 +0100,Orlondow 写道:

      ...也转载于 IIC 的 Cormen-Leiserson-Rivest。哪个是 最简单的 去寻找。

      是的,我确实有 Cormen 等人,但我从来没有抬头看 当我想要循环检测时,“强连接组件”。谢谢,我会 看看它。 :-)

      在有向图中找到一个循环 (你不在乎哪个周期)只要 因为存在一个,所以你不需要 过度使用 SCC。平原老深度 先搜索DFS(在同一章节 CLRS) 就足够了。

      因此,粗略地说,当您遍历目录树时,创建一个 DAG,它表示树的结构,其中节点处的数据引用文件的 inode。然后,您只需检查以确保您不会多次访问一个节点。

      【讨论】:

      • 在有向图中,而不是在 DAG 中。很明显,有向无环图中没有循环:)
      • 啊,你发现了我故意放在那里测试你的错误
      【解决方案4】:

      也许我在这里有点昏暗,但不是您可以创建循环的两种方式:

      • 通过创建符号链接
      • 通过安装两次

      要处理这些问题,您可以在开始索引之前获取挂载列表,并且 ifnore 除了第一个相同 fs 之外的所有内容,并且您可以在索引过程中遇到链接时忽略它们。

      【讨论】:

        【解决方案5】:

        简单的方法。只需对目录树进行深度优先树遍历,在您前进的过程中保留一堆节点。在您访问的每个节点上,如果该节点已经在堆栈中,则您有一个循环。

         // here's a stack of nodes
        node stack[1000];
        
        walk(node, level){
            if (node in stack[0..level-1]) then there is a cycle
            else
                stack[level] = node
                for each subnode x of node
                    walk(x, level+1)
        }
        

        【讨论】:

        • 这效率不高。我正在寻找一种有效的算法
        • @suresh:只有在有共享子树的情况下才会低效。如果这问题太大,那么您需要将节点标记为“已访问”。
        • 我认为这是正确的答案,这就是 find 命令检测文件系统循环的方式
        【解决方案6】:

        正如其他人所说,如果您意识到路径是文件名的一部分,则文件系统中不存在循环之类的东西,除非它是循环符号链接。

        例如,如果您将某个发行版(比如说 Debian)引导到一个循环设备,甚至是一个目录,然后在 Debian 机器上执行此操作,那么您现在已经复制了很多东西。

        例如,假设您正在运行 Debian Lenny,并将它的最小副本引导到 /lenny。

        /lenny/usr/* 将与 /usr/* 相同。没有“便宜”的方法可以避免这种情况。

        由于您已经在每个节点上调用了 stat() (我假设您正在使用 ftw() / ftw64() ,您也可以:

        • 让 ftw() 的回调将节点的名称插入到数组中,该数组具有可以存储不太可能发生冲突的文件哈希的结构成员。 md5 不会为此而削减它。
        • 根据该摘要和文件名(不是路径)更新哈希表。

        这不会加快您的扫描速度,但会大大缩短搜索时间。

        如果您正确使用线程并设置关联,则哈希和索引可以在一个核心上发生,而另一个是 i/o 绑定(当多个核心可用时)。

        但是,“只是”检查重复的挂载并不能解决问题,而且我确信您的程序会想要返回所有名为“foo”的文件的位置,即使有四个相同的副本要提及.

        【讨论】:

          【解决方案7】:

          这通常被称为“循环”。所以你要实现“循环检测”。有很多方法可以做到这一点;我不知道这是否适合家庭作业,但一种简单但不一定是最佳的方法是通过指针追踪。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2010-10-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-08-25
            • 2019-02-02
            • 1970-01-01
            相关资源
            最近更新 更多