[英]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.