[英]How do you get the size of a file in the linux 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 和 dentry,但仍然迷路了。
对该函数的调用取决于您使用的内核版本。 这两个参数版本是在 3.8 和 3.9 之间引入的。 因此,如果您使用的是内核 3.8 或更早版本,则需要“三个参数”,而 3.9 以后,则需要两个参数。
如果你真的想在内核模式下这样做,在比 3.9 更旧的内核上,你最好使用vfs_fstat
或vfs_stat
但是,处理内核中的文件是不受欢迎的,您可能需要考虑是否没有更好的替代方案 - 例如,如果您想将一些文件内容加载到系统上的主板的内存中,您可以在用户模式进程中加载文件,然后通过一些私有的 IOCTL 类型函数将加载的部分传递到内核中。 这更加“内核友好”,如果您打算尝试将您的驱动程序/模块包含在整个内核源代码中,您可能需要这样做。
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
。
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;
}
如果您已经有一个来自filp_open
的打开file* filp
,您可以像这样读取大小:
loff_t size = i_size_read(file_inode(filp));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.