你如何在linux内核中获得文件的大小?

时间:2013-09-23 18:16:20

标签: c linux linux-kernel kernel

我找到了这个链接(http://www.spinics.net/lists/newbies/msg41016.html)并且一直在研究这样做。所以我在内核模块中编写了代码:

#include <linux/path.h>
#include <linux/namei.h>
#include <linux/fs.h>

struct path p;
struct kstat ks;
kern_path(filepath, 0, &p);
vfs_getattr(&p, &ks);
printk(KERN_INFO "size: %lld\n", ks.size);

因为以下内容无法编译:

/root/kernelmodule/hello.c:15: warning: passing argument 1 of ‘vfs_getattr’ from incompatible pointer type
include/linux/fs.h:2563: note: expected ‘struct vfsmount *’ but argument is of type ‘struct path *’
/root/kernelmodule/hello.c:15: warning: passing argument 2 of ‘vfs_getattr’ from incompatible pointer type
include/linux/fs.h:2563: note: expected ‘struct dentry *’ but argument is of type ‘struct kstat *’
/root/kernelmodule/hello.c:15: error: too few arguments to function ‘vfs_getattr’

所以我真的很困惑,因为我正在查看这个文档:http://lxr.free-electrons.com/source/fs/stat.c#L40

现在我在/linux/fs.h里面看到vfs_getattr的原型是:

extern int vfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);

有人可以帮助我实施吗?我正在阅读vfsmount并拒绝但仍然丢失。

2 个答案:

答案 0 :(得分:3)

对此函数的调用会根据您使用的内核版本而更改。两个参数版本介于3.8和3.9之间。因此,如果你使用内核3.8或之前,你需要“三个参数”,而3.9以后,你需要两个参数。

如果你真的想在内核模式下执行此操作,在比3.9更旧的内核上,最好使用vfs_fstatvfs_stat

然而,处理内核中的文件是不受欢迎的,你可能想要考虑是否有更好的替代方案 - 例如,如果你想将一些文件内容加载到一块板的内存中在您的系统上,您可以在用户模式进程中加载​​文件,然后通过一些私有IOCTL类型函数将加载的部分传递到内核中。这更加“内核友好”,如果您计划将驱动程序/模块包含在整个内核源代码中,您可能需要这样做。

答案 1 :(得分:0)

vfs_stat是执行此操作的选项。

下面是一个示例:

#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/stat.h>

static char *load_file(char* filename, int *input_size)
{
        struct kstat *stat;
        struct file *fp;
        mm_segment_t fs;
        loff_t pos = 0;
        char *buf;

        fp = filp_open(filename, O_RDWR, 0644);
                if (IS_ERR(fp)) {
                        printk("Open file error!\n");
                        return ERR_PTR(-ENOENT);
        }

        fs = get_fs();
        set_fs(KERNEL_DS);
        
        stat =(struct kstat *) kmalloc(sizeof(struct kstat), GFP_KERNEL);
        if (!stat)
                return ERR_PTR(-ENOMEM);

        vfs_stat(filename, stat);
        *input_size = stat->size;

        buf = kmalloc(*input_size, GFP_KERNEL);
                if (!buf) {
                        kfree(stat);
                        printk("malloc input buf error!\n");
                        return ERR_PTR(-ENOMEM);
                }
        kernel_read(fp, buf, *input_size, &pos);

        filp_close(fp, NULL);
        set_fs(fs);
        kfree(stat);
        return buf;
}

由于大小未知,因此我们需要在函数内部进行kmalloc分配,因此buf需要在以后不再使用时kfree