内核态获取文件详细信息

内核态获取文件详细信息
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/syscalls.h>
#include <asm/unistd.h>
#include <asm/uaccess.h>
#define MY_FILE "/root/LogFile"
char buf[128];
struct file *file = NULL;
static int __init init(void)
{
printk("Hello, I'm the module that intends to write messages to file.\n");

if(file == NULL)
file = filp_open(MY_FILE, O_RDWR | O_APPEND | O_CREAT, 0644);
if (IS_ERR(file)) {
printk("error occured while opening file %s, exiting...\n", MY_FILE);
return 0;
}
  return 0;
}
static void __exit fini(void)
{
if(file != NULL)
filp_close(file, NULL);
}
module_init(init);
module_exit(fini);
MODULE_LICENSE("GPL");
其实上面的struct file结构体就包含了任何我们想要的关于文件相关的东西
struct file结构体定义在/linux/include/linux/fs.h(Linux 2.6.32内核)中,其原型是:
struct file {
/*
* fu_list becomes invalid after file_free is called and queued via
* fu_rcuhead for RCU freeing
*/
union {
struct list_head    fu_list;
struct rcu_head     fu_rcuhead;
} f_u;
struct path        f_path;
#define f_dentry    f_path.dentry   //关注对象
#define f_vfsmnt    f_path.mnt
const struct file_operations    *f_op;
spinlock_t        f_lock;  /* f_ep_links, f_flags, no IRQ */
atomic_long_t        f_count;
unsigned int         f_flags;
fmode_t            f_mode;
loff_t            f_pos;
struct fown_struct    f_owner;
const struct cred    *f_cred;
struct file_ra_state    f_ra;

u64            f_version;
#ifdef CONFIG_SECURITY
void            *f_security;
#endif
/* needed for tty driver, and maybe others */
void            *private_data;

#ifdef CONFIG_EPOLL
/* Used by fs/eventpoll.c to link all the hooks to this file */
struct list_head    f_ep_links;
#endif /* #ifdef CONFIG_EPOLL */
struct address_space    *f_mapping;
#ifdef CONFIG_DEBUG_WRITECOUNT
unsigned long f_mnt_write_state;
#endif
};
二、作用:
文件结构体代表一个打开的文件,系统中每个打开的文件在内核空间都有一个关联的struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。在内核创建和驱动源码 中,struct file的指针通常被命名为file或filp。
三、个字段详解:
1、
union {
struct list_head fu_list;
struct rcu_head rcuhead;
}f_u;
其中的struct list_head定义在 linux/include/linux/list.h中,原型为:
21struct list_head {
  22        struct list_head *next, *prev;
23};

list_head是内核中最常用的建立双向循环链表的结构,在此用于通用文件对象链表的指针。
struct rcu_head定义在linux/include/linux/rcupdate.h中,其原型为:
50struct rcu_head {
  51        struct rcu_head *next;
52        void (*func)(struct rcu_head *head);
53};

RCU(Read-Copy Update)是Linux 2.6内核中新的锁机制,具体参考:
http://www.ibm.com/developerworks/cn/linux/l-rcu/
在此用于更新文件。fu_list在file_free()函数被调用以后就无效了,队列通过rcu_head来释放RCU。
2、struct path f_path;
被定义在linux/include/linux/namei.h中,其原型为:
32struct path {
  33        struct vfsmount *mnt;
34        struct dentry *dentry;
35};

在早些版本的内核中并没有此结构,而是直接将path的两个数据成员作为struct file的数据成员,
struct vfsmount *mnt的作用是指出该文件的已安装文件系统,
struct dentry *dentry是与文件相关的目录项对象。
详细:http://hi.baidu.com/wwwkljoel/blog/item/dbf19eda975dc1d7b6fd48bc.html

entry
一、dentry的定义   
dentry的中文名称是目录项,是Linux文件系统中某个索引节点(inode)的链接。这个索引节点可以是文件,也可以是目录。


二、dentry的结构:以下是dentry的结构体
struct dentry {
atomic_t d_count; 目录项对象使用计数器
unsigned int d_flags; 目录项标志
struct inode * d_inode; 与文件名关联的索引节点
//关注
struct dentry * d_parent; 父目录的目录项对象
struct list_head d_hash; 散列表表项的指针
struct list_head d_lru; 未使用链表的指针
struct list_head d_child; 父目录中目录项对象的链表的指针
struct list_head d_subdirs;对目录而言,表示子目录目录项对象的链表
struct list_head d_alias; 相关索引节点(别名)的链表
int d_mounted; 对于安装点而言,表示被安装文件系统根项
struct qstr d_name; 文件名
unsigned long d_time; /* used by d_revalidate */
struct dentry_operations *d_op; 目录项方法
struct super_block * d_sb; 文件的超级块对象
vunsigned long d_vfs_flags;
void * d_fsdata;与文件系统相关的数据
unsigned char d_iname [DNAME_INLINE_LEN]; 存放短文件名
};

3、const struct file_operations *f_op;
被定义在linux/include/linux/fs.h中,其中包含着与文件关联的操作,如:
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
等。 当打开一个文件时,内核就创建一个与该文件相关联的struct file结构,其中的*f_op就指向的是具体对该文件进行操作的函数。例如用户调用系统调用read来读取该文件的内容时,那么系统调用read最终会 陷入内核调用sys_read函数,而 sys_read最终会调用与该文件关联的struct file结构中的f_op->read函数对文件内容进行读取。
4、atomic_t f_count;
atomic_t被定义为:
typedef struct { volatile int counter; } atomic_t;
volatile 修饰字段告诉gcc不要对该类型的数据做优化处理,对它的访问都是对内存的访问,而不是对寄存器的访问。本质是int类型,之所以这样写是让编译器对基于 该类型变量的操作进行严格的类型检查。此处f_count的作用是记录对文件对象的引用计数,也即当前有多少个使用CLONE_FILES标志克隆的进程 在使用该文件。典型的应用是在POSIX线程中。就像在内核中普通的引用计数模块一样,最后一个进程调用put_files_struct()来释放文件 描述符。
5、unsigned int f_flags;
当打开文件时指定的标志,对应系统调用open的int flags参数。驱动程序为了支持非阻塞型操作需要检查这个标志。
六、mode_t f_mode;
对文件的读写模式,对应系统调用open的mod_t mode参数。如果驱动程序需要这个值,可以直接读取这个字段。
mod_t被定义为:
typedef unsigned int __kernel_mode_t;
typedef __kernel_mode_t mode_t;
7、loff_t f_pos;
当前的文件指针位置,即文件的读写位置。
loff_t被定义为:
typedef long long __kernel_loff_t;
typedef __kernel_loff_t loff_t;
8、struct fown_struct f_owner;
struct fown_struct在linux/include/linux/fs.h被定义,原型为:
 688struct fown_struct {
689  rwlock_t lock;          /* protects pid, uid, euid fields */
690  struct pid *pid;        /* pid or -pgrp where SIGIO should be sent */
691  enum pid_type pid_type;/*Kind of process group SIGIO should be sent to*/
692  uid_t uid, euid;        /* uid/euid of process setting the owner */
693  int signum;             /* posix.1b rt signal to be delivered on IO */ 694};
该结构的作用是通过信号进行I/O时间通知的数据。
9、unsigned int f_uid, f_gid;
标识文件的所有者id,所有者所在组的id.
10、struct file_ra_state f_ra;
struct file_ra_state结构被定义在/linux/include/linux/fs.h中,原型为:
699struct file_ra_state {
 700        pgoff_t start;                  /* where readahead started */
701        unsigned long size;             /* # of readahead pages */
702        unsigned long async_size;       /* do asynchronous readahead when
703                                           there are only # of pages ahead */
704
705        unsigned long ra_pages;         /* Maximum readahead window */
706        unsigned long mmap_hit;       /* Cache hit stat for mmap accesses */
707        unsigned long mmap_miss;  /* Cache miss stat for mmap accesses */
708       unsigned long prev_index;       /* Cache last read() position */
709     unsigned int prev_offset; /* Offset where last read() ended in a page */
710};
文件预读状态,文件预读算法使用的主要数据结构,当打开一个文件时,f_ra中出了perv_page(默认为-1)和ra_apges(对该文件允许的最大预读量)这两个字段外,其他的所有字端都置为0。
11、unsigned long f_version;
记录文件的版本号,每次使用后都自动递增。
12、
#ifdef CONFIG_SECURITY
void *f_security;
#endif
此处我的理解是如果在编译内核时配置了安全措施,那么struct file结构中就会有void *f_security数据项,用来描述安全措施或者是记录与安全有关的信息。
13、void *private_data;
系统在调用驱动程序的open方法前将这个指针置为NULL。驱动程序可以将这个字段用于任意目的,也可以忽略这个字段。驱动程序可以用这个字段指向已分配的数据,但是一定要在内核释放file结构前的release方法中清除它。
14、
#ifdef CONFIG_EPOLL
/* Used by fs/eventpoll.c to link all the hooks to this file */
struct list_head f_ep_links;
spinlock_t f_ep_lock;
#endif /* #ifdef CONFIG_EPOLL */
被用在fs/eventpoll.c来链接所有钩到这个文件上。其中f_ep_links是文件的事件轮询等待者链表的头,f_ep_lock是保护f_ep_links链表的自旋锁。
15、struct address_space *f_mapping;
struct address_space被定义在/linux/include/linux/fs.h中,此处是指向文件地址空间的指针。

struct address_space {
struct inode  *host;  /* owner: inode, block_device */
struct radix_tree_root page_tree; /* radix tree of all pages */
rwlock_t  tree_lock; /* and rwlock protecting it */
unsigned int  i_mmap_writable;/* count VM_SHARED mappings */
struct prio_tree_root i_mmap;  /* tree of private and shared mappings */
struct list_head i_mmap_nonlinear;/*list VM_NONLINEAR mappings */
spinlock_t  i_mmap_lock; /* protect tree, count, list */
unsigned int  truncate_count; /* Cover race condition with truncate */
unsigned long  nrpages; /* number of total pages */
pgoff_t   writeback_index;/* writeback starts here */
const struct address_space_operations *a_ops; /* methods */
unsigned long  flags;  /* error bits/gfp mask */
struct backing_dev_info *backing_dev_info; /* device readahead, etc */
spinlock_t  private_lock; /* for use by the address_space */
struct list_head private_list; /* ditto */
struct address_space *assoc_mapping; /* ditto */
} __attribute__((aligned(sizeof(long))));

内核中用inode结构表示具体的文件,而用file结构表示打开的文件描述符。Linux2.6.27内核中,inode结构体具体定义如下:
struct inode
{
struct hlist_node   i_hash;
struct list_head   i_list;
struct list_head   i_sb_list;
struct list_head   i_dentry;
unsigned long       i_ino;
atomic_t       i_count;
unsigned int       i_nlink;
uid_t           i_uid;       
/*inode的id*/
gid_t           i_gid;       /*inode的组id*/
dev_t           i_rdev; //该成员表示设备文件的inode结构,它包含了真正的设备编号。
u64           i_version;
loff_t           i_size;  
/*inode多代表的文件的大小*/
#ifdef __NEED_I_SIZE_ORDERED
seqcount_t       i_size_seqcount;
#endif
struct timespec       i_atime;       
/*inode最后一次存取的时间*/
struct timespec       i_mtime;       /*inode最后一次修改的时间*/
struct timespec       i_ctime;       /*inode的创建时间*/
unsigned int       i_blkbits;          /*inode在做I/O时的区块大小*/
blkcnt_t       i_blocks;                 /*inode所石油的block块数*/
unsigned short          i_bytes;
umode_t           i_mode;   
/*inode的权限*/
spinlock_t       i_lock;   /* i_blocks, i_bytes, maybe i_size */
struct mutex       i_mutex;
struct rw_semaphore   i_alloc_sem;
const struct inode_operations   *i_op;
const struct file_operations   *i_fop;   /* former ->i_op->default_file_ops */
struct super_block   *i_sb;
struct file_lock   *i_flock;
struct address_space   *i_mapping;
struct address_space   i_data;
#ifdef CONFIG_QUOTA
struct dquot       *i_dquot[MAXQUOTAS];
#endif
struct list_head   i_devices;   
/*若是字符设备,为其对应的cdev结构体指针*/
union {
struct pipe_inode_info   *i_pipe;
struct block_device   *i_bdev;    
/*若是块设备,为其对应的cdev结构体指针*/
struct cdev       *i_cdev; //该成员表示字符设备的内核的 内部结构。当inode指向一个字符设备文件时,该成员包含了指向struct cdev结构的指针,其中cdev结构是字符设备结构体。
};
int           i_cindex;

__u32           i_generation;

#ifdef CONFIG_DNOTIFY
unsigned long       i_dnotify_mask; /* Directory notify events */
struct dnotify_struct   *i_dnotify; /* for directory notifications */
#endif

#ifdef CONFIG_INOTIFY
struct list_head   inotify_watches; /* watches on this inode */
struct mutex       inotify_mutex;   /* protects the watches list */
#endif

unsigned long       i_state;
unsigned long       dirtied_when;   /* jiffies of first dirtying */

unsigned int       i_flags;

atomic_t       i_writecount;
#ifdef CONFIG_SECURITY
void           *i_security;
#endif
void           *i_private; /* fs or device private pointer */

};

ok你想要文件的什么直接打印就可以了
posted @ 2011-06-24 22:50  阳光特区  阅读(2147)  评论(0编辑  收藏  举报