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

时间:2015-09-16 19:36:46

标签: linux linux-kernel kernel

我想实现一个树遍历函数,它打印给定目录的所有内容 在内核中。我知道如何在用户空间中执行此操作,但我的要求是在内核空间中使用它。 为此,我正在研究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编号(这就是我在回调中除了名称之外的内容)来做到这一点吗?

1 个答案:

答案 0 :(得分:2)

例如,从readdir syscall implementation调用

vfs_readdir。它使用fillonedir作为回调,反过来可以很容易理解:它的第一个参数只是vfs_readdir的最后一个参数,所有其他参数(namenamelen,{{ 1}},offsetino)按原样复制到用户空间。

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

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

至于iterate_dir参数,你不能将它用于开放的给定inode(内核只有inode号没有 open 文件的机制)。使用ino或类似内容。