Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何在文件系统中查找循环?_C_Linux - Fatal编程技术网

C 如何在文件系统中查找循环?

C 如何在文件系统中查找循环?,c,linux,C,Linux,在Linux中如何在文件系统中查找循环?我正在为所有文件编制索引,以便快速搜索(O(1))。。。我正在使用c编程语言来实现,通过使用dir.h中的库函数。。。。我可以扫描整个文件系统,但如果文件系统中有循环,它就会进入一个循环(例如循环装载)。。。如何在文件系统中查找循环。。我见过updatedb命令在文件系统中有循环时报告。。。我不明白逻辑。。。有人能帮你找到解决办法吗?这通常被称为“循环”。所以你想实施“循环检测”。有很多方法可以做到这一点;我不知道这是否适用于家庭作业,但一种简单但不一定是

在Linux中如何在文件系统中查找循环?我正在为所有文件编制索引,以便快速搜索(O(1))。。。我正在使用c编程语言来实现,通过使用dir.h中的库函数。。。。我可以扫描整个文件系统,但如果文件系统中有循环,它就会进入一个循环(例如循环装载)。。。如何在文件系统中查找循环。。我见过updatedb命令在文件系统中有循环时报告。。。我不明白逻辑。。。有人能帮你找到解决办法吗?

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

防止在图形中重新扫描节点的一般方法是在传递节点时标记节点,然后忽略标记的节点。如果您不想修改正在扫描的图形,那么这就不太实际,因此需要一种从外部标记节点的方法。在linux下,我能想到的最简单的方法是为您访问的每个目录在设备/inode中存储一个索引。然后,当您查看目录时,首先检查您是否尚未看到任何具有相同设备/inode的目录。这不仅处理循环,还处理相互合并的树

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


在存储数据时,您可能需要查看一棵树或二叉树。

我在这里找到了关于以下内容的有趣评论:

Steinar H.Gunderson写道:

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

…也复制在科曼-雷瑟森河,IIC。那是 容易的 找到

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

求有向图中的圈 (你不在乎哪个周期)只要 因为存在一个,所以你不需要这样做 与SCC一起过火。平原旧深度 首次搜索DFS(在同一章中 这就足够了


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

也许我在这里有点糊涂,但创建循环的两种方法不是:

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

为了解决这些问题,您可以在开始索引之前获得挂载的列表,并删除除第一个外的所有相同的fs,并且您可以在索引过程中忽略遇到它们的链接。

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

 // 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)
}

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

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

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

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

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

  • 让ftw()的回调函数将节点的名称插入一个数组中,该数组的结构成员可以存储不太可能发生冲突的文件哈希。md5不会因此而对其进行剪切
  • 基于该摘要和文件名(而不是路径)更新哈希表
这不会有加快扫描速度的危险,但会大大缩短搜索时间

如果正确使用线程并设置关联,则散列和索引可以在一个内核上进行,而另一个内核是i/o绑定的(当多个内核可用时)


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

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


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

堆栈溢出对新用户来说有点不友好。投票否决某人时,请留下评论,解释您为什么这样做,并给出一些提示,说明他们应该做些什么来改进。在有向图中,而不是在DAG中。这是q很明显,在有向无环图中没有圈:)啊,你发现了我故意犯的错误,我放在那里是为了测试你,这是没有效率的。。我想找一个高效的algorithm@suresh:只有当存在共享子树时,它才是低效的。如果这是一个太大的问题,那么您需要将节点标记为“已访问”。我认为这是正确的答案,这就是find命令检测文件系统循环的方式