【问题标题】:How to read contents of a directory recursively in Linux Kernel?如何在 Linux 内核中递归读取目录的内容?
【发布时间】:2015-12-13 13:12:32
【问题描述】:

我想实现一个树遍历函数,它打印给定目录的所有内容 在内核中。我知道如何在用户空间中做到这一点,但我的要求是在内核空间中拥有它。 为此,我正在研究 vfs_readdir 函数,但对其用法有点困惑。 假设我将从其他内核模块调用我的遍历函数,这意味着该请求不会来自用户空间。现在的问题是如何调用 vfs_readdir 并使用该信息递归解析给定目录。从 vfs_readdir 的定义 extern int vfs_readdir(struct file *, filldir_t, void *);

我可以使用 filp_open() 之类的函数从文件路径中获取 struct file *,据我了解,filldir_t 是一个函数指针,用于填充由 void * 指向的用户提供的缓冲区的回调函数。但就我而言,我不需要将任何信息传回给用户。我应该在 void * 地方传递什么? 查看 filldir 函数定义

static int filldir(void * __buf, const char * name, int namlen, loff_t offset, ino_t ino, unsigned int d_type);

这个函数的参数是从哪里来的。我的假设是 vfs_readdir 依次调用类似 file->f_op_readdir(file,but,filler); 这是否在内部执行某些操作并填写参数以调用回调函数? 现在这是一个层次。我应该怎么做才能递归打印给定目录中的所有文件。我想我需要在我自己的回调函数中做一些事情。但是我只有一些关于通过这个回调函数传递的文件的信息,比如文件名、inode 号等。我怎么知道它是使用此信息的常规文件还是目录。我的意思是我没有关于该文件的 dentry 或 inode 数据结构。任何建议如何做到这一点? 另外,如果我想在回调函数中删除一个文件,我可以通过使用inode号来做到这一点吗(除了名称之外,我在回调中有什么)我应该怎么做?

【问题讨论】:

  • 欢迎来到 Stack Exchange 网络!您应该对您的 - 或任何 - 问题提供有用的答案。最好的答案应该被接受,以给予回答者荣誉并通知其他人您的问题已解决。见How does accepting an answer work?

标签: linux linux-kernel kernel


【解决方案1】:

vfs_readdir 被调用,例如,来自readdir syscall implementation。它使用fillonedir作为回调,这反过来又很容易理解:它的第一个参数只是vfs_readdir的最后一个参数,所有其他参数(namenamelenoffsetino,@987654329 @) 被原样复制到用户空间中。

注意,vfs_readdir 的回调是在 inode 互斥锁锁定 (inode->i_mutex) 的情况下执行的。可能您不应该打开该回调的子目录。相反,将子目录的名称保存在某处,然后在 vfs_readdir 调用之后打开它。这与您在用户空间中遍历目录树的方式非常相似。

请注意,从 3.11 版开始,内核使用另一种方式来迭代目录中的条目:iterate_dir。它的第二个参数结合了回调和特定于回调的参数,还包括文件中的当前位置。除了第一个参数,callback 接受的参数和之前一样。

至于ino 参数,您不能将它用于打开给定的inode(内核只是没有按inode 编号打开 文件的机制)。使用 filp_open 或类似名称。

【讨论】:

  • 如果我不打算在回调中打开子目录。我应该如何决定文件是否是目录(如果它是子目录,我可以保存它)而不打开它,因为它只有一个文件名
  • 您可以使用d_type 来确定条目类型。顺便说一句,你在用户空间也这样做,不是吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-06
  • 2018-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-23
  • 1970-01-01
相关资源
最近更新 更多