如何在Linux内核中递归读取目录内容?

use*_*345 5 linux kernel linux-kernel

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

\n\n

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

\n\n

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

\n\n

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

\n

Tsy*_*rev 5

vfs_readdir例如,从readdir 系统调用实现中调用。它使用fillonedir回调,这也很容易理解:它的第一个参数只是 的最后一个参数vfs_readdir,所有其他参数(name, namelen, offset, ino, d_type)都按原样复制到用户空间。

注意,回调函数vfs_readdir是在索引节点互斥锁锁定(inode->i_mutex)的情况下执行的。也许您不应该打开包含该回调的子目录。相反,将子目录的名称保存在某处,并在调用 vfs_readdir打开它。这与在用户空间中遍历目录树的方式非常相似。

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

至于ino参数,您不能使用它来打开给定的 inode(内核没有通过 inode 编号打开文件的机制)。使用filp_open或类似。