2

我找到了这个链接(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 和 dentry,但仍然迷路。

4

4 回答 4

5

对该函数的调用会根据您使用的内核版本而有所不同。两个参数版本是在 3.8 和 3.9 之间引入的。因此,如果您使用的是内核 3.8 或更早版本,则需要“三个参数”,而 3.9 及更高版本,则需要两个参数。

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

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

于 2013-09-23T20:10:44.760 回答
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

于 2020-06-22T07:19:53.913 回答
0

vfs_stat 返回一个奇怪的错误:modpost:“vfs_fstatat”[/mydir/module.ko] 未定义!所以我更喜欢使用 vfs_getattr 或 vfs_llseek

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

    fp = filp_open(filename, O_RDONLY, 0644);// O_RDWR O_RDONLY O_WRONLY O_APPEND O_CREAT
            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);

    rc = vfs_getattr(&fp->f_path, stat, STATX_SIZE, AT_STATX_SYNC_AS_STAT);
    if(rc != 0){
        printk("vfs_getattr Error");
    }
    //OR symply
    //mPos = vfs_llseek(fp, 0, SEEK_END);
    
    input_size = stat->size;
    //input_size = (int)mPos;

    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;
}
于 2021-09-24T07:29:44.057 回答
0

如果你已经有一个 open file* filpfrom,filp_open你可以像这样读取大小:

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
    loff_t size = i_size_read(file_inode(filp));
#else   
    loff_t size = i_size_read(filp->f_path.dentry->d_inode);
#endif
于 2021-11-26T13:23:02.017 回答