hello.c¡¡¡¡´úÂë: ¡¡¡¡¡¡¡¡#include "hello.h" ¡¡¡¡¡¡¡¡strUCt inode * hello_get_inode(struct super_block *, int, struct hello_dir_entry *); ¡¡¡¡¡¡¡¡int hello_readdir(struct file * filp, void * dirent, filldir_t filldir) ¡¡¡¡{ ¡¡¡¡printk("hello_readdir\n"); ¡¡¡¡¡¡ struct hello_dir_entry * de; ¡¡¡¡¡¡ unsigned int ino; ¡¡¡¡¡¡ int i; ¡¡¡¡¡¡ struct inode *inode = filp->f_dentry->d_inode; ¡¡¡¡¡¡¡¡¡¡ ino = inode->i_ino; ¡¡¡¡¡¡ de = (struct hello_dir_entry *) inode->u.generic_ip; ¡¡¡¡¡¡ if (!de) ¡¡¡¡¡¡¡¡¡¡return -EINVAL; ¡¡¡¡¡¡ i = filp->f_pos; ¡¡¡¡¡¡ switch (i) { ¡¡¡¡¡¡¡¡¡¡case 0: ¡¡¡¡¡¡¡¡¡¡¡¡ if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡return 0; ¡¡¡¡¡¡¡¡¡¡¡¡ i++; ¡¡¡¡¡¡¡¡¡¡¡¡ filp->f_pos++; ¡¡¡¡¡¡¡¡¡¡¡¡ /* fall through */ ¡¡¡¡¡¡¡¡¡¡case 1: ¡¡¡¡¡¡¡¡¡¡¡¡ if (filldir(dirent, "..", 2, i, ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡filp->f_dentry->d_parent->d_inode->i_ino, ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡DT_DIR) < 0) ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡return 0; ¡¡¡¡¡¡¡¡¡¡¡¡ i++; ¡¡¡¡¡¡¡¡¡¡¡¡ filp->f_pos++; ¡¡¡¡¡¡¡¡¡¡¡¡ /* fall through */ ¡¡¡¡¡¡¡¡¡¡default: ¡¡¡¡¡¡¡¡¡¡¡¡ de = de->subdir; ¡¡¡¡¡¡¡¡¡¡¡¡ i -= 2; ¡¡¡¡¡¡¡¡¡¡¡¡ for (;;) { ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡if (!de) ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ return 1; ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡if (!i) ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ break; ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡de = de->next; ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡i--; ¡¡¡¡¡¡¡¡¡¡¡¡ } ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ do { ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡if (filldir(dirent, de->name, de->namelen, filp->f_pos, ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ de->low_ino, de->mode >> 12) < 0) ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ return 0; ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡filp->f_pos++; ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡de = de->next; ¡¡¡¡¡¡¡¡¡¡¡¡ } while (de); ¡¡¡¡¡¡ } ¡¡¡¡¡¡ return 1; ¡¡¡¡} ¡¡¡¡¡¡¡¡int hello_d_revalidate(struct dentry *res, int i){printk("d_revalidate\n");return 0;} ¡¡¡¡int hello_d_hash(struct dentry *res, struct qstr *name){printk("d_hash\n");return 0;} ¡¡¡¡int hello_d_compare(struct dentry *res, struct qstr *name, struct qstr *old) ¡¡¡¡{printk("d_compare\n");return 0;} ¡¡¡¡int hello_d_delete(struct dentry *res){printk("d_delete\n");return 0;} ¡¡¡¡void hello_d_release(struct dentry *res){printk("d_release\n");} ¡¡¡¡void hello_d_iput(struct dentry *res, struct inode *inode){printk("d_iput\n");} ¡¡¡¡¡¡¡¡struct dentry_operations hello_lookup_dops = { ¡¡¡¡¡¡ /*d_revalidate:¡¡ hello_d_revalidate, ¡¡¡¡¡¡ d_hash:¡¡¡¡¡¡hello_d_hash, ¡¡¡¡¡¡ d_compare:¡¡ hello_d_compare,*/ ¡¡¡¡¡¡ d_delete:¡¡ hello_d_delete, ¡¡¡¡¡¡ d_release:¡¡ hello_d_release, ¡¡¡¡¡¡ /*d_iput:¡¡¡¡¡¡hello_d_iput*/ ¡¡¡¡}; ¡¡¡¡¡¡¡¡struct dentry *hello_lookup(struct inode * dir, struct dentry *dentry) ¡¡¡¡{ ¡¡¡¡¡¡ struct inode *inode; ¡¡¡¡¡¡ struct hello_dir_entry * de; ¡¡¡¡¡¡ int error; ¡¡¡¡¡¡¡¡¡¡ error = -ENOENT; ¡¡¡¡¡¡ inode = NULL; ¡¡¡¡¡¡ de = (struct hello_dir_entry *) dir->u.generic_ip; ¡¡¡¡¡¡ if (de) { ¡¡¡¡¡¡¡¡¡¡for (de = de->subdir; de ; de = de->next) { ¡¡¡¡¡¡¡¡¡¡¡¡ if (!de !de->low_ino) ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡continue; ¡¡¡¡¡¡¡¡¡¡¡¡ if (de->namelen != dentry->d_name.len) ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡continue; ¡¡¡¡¡¡¡¡¡¡¡¡ if (!memcmp(dentry->d_name.name, de->name, de->namelen)) { ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡int ino = de->low_ino; ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡error = -EINVAL; ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡inode = hello_get_inode(dir->i_sb, ino, de); ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡break; ¡¡¡¡¡¡¡¡¡¡¡¡ } ¡¡¡¡¡¡¡¡¡¡} ¡¡¡¡¡¡ } ¡¡¡¡¡¡¡¡¡¡ if (inode) { ¡¡¡¡¡¡¡¡¡¡dentry->d_op = &hello_lookup_dops; ¡¡¡¡¡¡¡¡¡¡d_add(dentry, inode); ¡¡¡¡¡¡¡¡¡¡return NULL; ¡¡¡¡¡¡ } ¡¡¡¡¡¡ return ERR_PTR(error); ¡¡¡¡} ¡¡¡¡/************************************************************************************************************/ ¡¡¡¡static struct inode_operations hello_root_inode_operations = { ¡¡¡¡¡¡ lookup:¡¡¡¡¡¡hello_lookup, ¡¡¡¡}; ¡¡¡¡¡¡¡¡static struct file_operations hello_file_operations = { ¡¡¡¡¡¡ readdir:¡¡ hello_readdir, ¡¡¡¡};¡¡¡¡¡¡¡¡¡¡¡¡struct hello_dir_entry hello_root = { ¡¡¡¡¡¡ low_ino:¡¡ HELLO_ROOT_INO, ¡¡¡¡¡¡ namelen:¡¡ 5, ¡¡¡¡¡¡ name:¡¡¡¡¡¡"/hello", ¡¡¡¡¡¡ mode:¡¡¡¡¡¡S_IFDIR S_IRUGO S_IXUGO, ¡¡¡¡¡¡ nlink:¡¡¡¡¡¡2, ¡¡¡¡¡¡ hello_iops:¡¡ &hello_root_inode_operations, ¡¡¡¡¡¡ hello_fops:¡¡ &hello_file_operations, ¡¡¡¡¡¡ parent:¡¡ &hello_root, ¡¡¡¡}; ¡¡¡¡¡¡¡¡struct inode * hello_get_inode(struct super_block * sb, int ino, ¡¡¡¡¡¡ struct hello_dir_entry * de) ¡¡¡¡{ ¡¡¡¡printk("hello_get_inode\n"); ¡¡¡¡¡¡ struct inode * inode; ¡¡¡¡¡¡¡¡¡¡ de_get(de); ¡¡¡¡¡¡ inode = iget(sb, ino); ¡¡¡¡¡¡ if (!inode) ¡¡¡¡¡¡¡¡¡¡goto out_fail; ¡¡¡¡¡¡ inode->u.generic_ip = (void *) de; ¡¡¡¡¡¡ if (de) { ¡¡¡¡¡¡¡¡¡¡if (de->mode) { ¡¡¡¡¡¡¡¡¡¡¡¡ inode->i_mode = de->mode; ¡¡¡¡¡¡¡¡¡¡¡¡ inode->i_uid = de->uid; ¡¡¡¡¡¡¡¡¡¡¡¡ inode->i_gid = de->gid; ¡¡¡¡¡¡¡¡¡¡} ¡¡¡¡¡¡¡¡¡¡if (de->size) ¡¡¡¡¡¡¡¡¡¡¡¡ inode->i_size = de->size; ¡¡¡¡¡¡¡¡¡¡if (de->nlink) ¡¡¡¡¡¡¡¡¡¡¡¡ inode->i_nlink = de->nlink; ¡¡¡¡¡¡¡¡¡¡if (de->owner) ¡¡¡¡¡¡¡¡¡¡¡¡ __MOD_INC_USE_COUNT(de->owner); ¡¡¡¡¡¡¡¡¡¡if (de->hello_iops) ¡¡¡¡¡¡¡¡¡¡¡¡ inode->i_op = de->hello_iops; ¡¡¡¡¡¡¡¡¡¡if (de->hello_fops) ¡¡¡¡¡¡¡¡¡¡¡¡ inode->i_fop = de->hello_fops; ¡¡¡¡¡¡ } ¡¡¡¡¡¡¡¡out: ¡¡¡¡¡¡ return inode; ¡¡¡¡¡¡¡¡out_fail: ¡¡¡¡¡¡ de_put(de); ¡¡¡¡¡¡ goto out; ¡¡¡¡}¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡/***********************************************************************************************************/ ¡¡¡¡¡¡¡¡void d_instantiate(struct dentry *entry, struct inode * inode) ¡¡¡¡{ ¡¡¡¡printk("d_instantiate\n"); ¡¡¡¡¡¡ if (!list_empty(&entry->d_alias)) BUG(); ¡¡¡¡¡¡ spin_lock(&dcache_lock); ¡¡¡¡¡¡ if (inode) ¡¡¡¡¡¡¡¡¡¡list_add(&entry->d_alias, &inode->i_dentry); ¡¡¡¡¡¡ entry->d_inode = inode; ¡¡¡¡¡¡ spin_unlock(&dcache_lock); ¡¡¡¡} ¡¡¡¡¡¡¡¡struct dentry * d_alloc_root(struct inode * root_inode) ¡¡¡¡{ ¡¡¡¡¡¡ struct dentry *res = NULL; ¡¡¡¡printk("d_alloc_root\n"); ¡¡¡¡¡¡ if (root_inode) { ¡¡¡¡¡¡¡¡¡¡res = d_alloc(NULL, &(const struct qstr) { "/", 1, 0 }); ¡¡¡¡¡¡¡¡¡¡if (res) { ¡¡¡¡¡¡¡¡¡¡¡¡ res->d_sb = root_inode->i_sb; ¡¡¡¡¡¡¡¡¡¡¡¡ res->d_parent = res; ¡¡¡¡¡¡¡¡¡¡¡¡ d_instantiate(res, root_inode); ¡¡¡¡¡¡¡¡¡¡} ¡¡¡¡¡¡ } ¡¡¡¡¡¡ return res; ¡¡¡¡} ¡¡¡¡¡¡¡¡void force_delete(struct inode *inode) ¡¡¡¡{ ¡¡¡¡printk("force_delete\n"); ¡¡¡¡¡¡ struct hello_dir_entry *de = inode->u.generic_ip; ¡¡¡¡¡¡¡¡¡¡¡¡¡¡ if (atomic_read(&inode->i_count) == 1) ¡¡¡¡¡¡¡¡¡¡inode->i_nlink = 0; ¡¡¡¡¡¡ if (atomic_dec_and_test(&de->count)) ¡¡¡¡¡¡¡¡¡¡printk("hello_root.count: %d\n", atomic_read(&de->count)); ¡¡¡¡} ¡¡¡¡¡¡¡¡static void hello_delete_inode(struct inode *inode) ¡¡¡¡{ ¡¡¡¡printk("hello_delete_inode\n"); ¡¡¡¡¡¡ struct hello_dir_entry *de = inode->u.generic_ip; ¡¡¡¡¡¡ inode->i_state = I_CLEAR; ¡¡¡¡¡¡ /*if (de) { ¡¡¡¡¡¡¡¡¡¡if (de->owner) ¡¡¡¡¡¡¡¡¡¡¡¡ __MOD_DEC_USE_COUNT(de->owner); ¡¡¡¡¡¡¡¡¡¡de_put(de); ¡¡¡¡¡¡ }*/ ¡¡¡¡} ¡¡¡¡¡¡¡¡static void hello_read_inode(struct inode * inode) ¡¡¡¡{ ¡¡¡¡printk("hello_read_inode\n"); ¡¡¡¡¡¡ inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; ¡¡¡¡} ¡¡¡¡¡¡¡¡static int hello_statfs(struct super_block *sb, struct statfs *buf) ¡¡¡¡{ ¡¡¡¡printk("hello_statfs\n"); ¡¡¡¡¡¡ return 0; ¡¡¡¡} ¡¡¡¡¡¡¡¡void hello_write_super(struct super_block *s) ¡¡¡¡{ ¡¡¡¡¡¡ printk("write_super\n"); ¡¡¡¡} ¡¡¡¡¡¡¡¡static struct super_operations hello_sops = { ¡¡¡¡¡¡ read_inode:¡¡ hello_read_inode, ¡¡¡¡¡¡ put_inode:¡¡ force_delete, ¡¡¡¡¡¡ delete_inode:¡¡ hello_delete_inode, ¡¡¡¡¡¡ write_super:¡¡ hello_write_super, ¡¡¡¡¡¡ /*statfs:¡¡¡¡¡¡hello_statfs,*/ ¡¡¡¡}; ¡¡¡¡¡¡¡¡struct dentry_operations hello_dops = { ¡¡¡¡¡¡ /*d_revalidate:¡¡ hello_d_revalidate, ¡¡¡¡¡¡ d_hash:¡¡¡¡¡¡hello_d_hash, ¡¡¡¡¡¡ d_compare:¡¡ hello_d_compare,*/ ¡¡¡¡¡¡ /*d_delete:¡¡ hello_d_delete,*/ ¡¡¡¡¡¡ d_release:¡¡ hello_d_release, ¡¡¡¡¡¡ /*d_iput:¡¡¡¡¡¡hello_d_iput*/ ¡¡¡¡}; ¡¡¡¡struct super_block *hello_read_super(struct super_block *s, void *data, ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡int silent) ¡¡¡¡{ ¡¡¡¡printk("hello_read_super\n");¡¡¡¡¡¡¡¡¡¡ struct inode * root_inode; ¡¡¡¡¡¡¡¡¡¡ s->s_blocksize = 1024; ¡¡¡¡¡¡ s->s_blocksize_bits = 10; ¡¡¡¡¡¡ s->s_magic = 0; ¡¡¡¡¡¡ s->s_op = &hello_sops; ¡¡¡¡¡¡ root_inode = hello_get_inode(s, HELLO_ROOT_INO, &hello_root); ¡¡¡¡¡¡ if (!root_inode) ¡¡¡¡¡¡¡¡¡¡goto out_no_root; ¡¡¡¡¡¡¡¡¡¡ s->s_root = d_alloc_root(root_inode); ¡¡¡¡¡¡ if (!s->s_root) ¡¡¡¡¡¡¡¡¡¡goto out_no_root; ¡¡¡¡¡¡ s->s_root->d_op = &hello_dops; ¡¡¡¡¡¡ return s; ¡¡¡¡¡¡¡¡out_no_root: ¡¡¡¡¡¡ printk("hello_read_super: get root inode failed\n"); ¡¡¡¡¡¡ iput(root_inode); ¡¡¡¡¡¡ return NULL; ¡¡¡¡} ¡¡¡¡¡¡¡¡¡¡¡¡hello.h ¡¡¡¡´úÂë: ¡¡¡¡¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡¡¡¡¡¡¡¡¡#define HELLO_ROOT_INO 1 ¡¡¡¡¡¡¡¡¡¡¡¡typedef¡¡ int (read_hello_t)(char *page, char **start, off_t off, ¡¡¡¡¡¡¡¡¡¡¡¡¡¡ int count, int *eof, void *data); ¡¡¡¡typedef¡¡ int (write_hello_t)(struct file *file, const char *buffer, ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡unsigned long count, void *data); ¡¡¡¡typedef int (get_info_t)(char *, char **, off_t, int); ¡¡¡¡¡¡¡¡struct hello_dir_entry { ¡¡¡¡¡¡ unsigned short low_ino; ¡¡¡¡¡¡ unsigned short namelen; ¡¡¡¡¡¡ const char *name; ¡¡¡¡¡¡ mode_t mode; ¡¡¡¡¡¡ nlink_t nlink; ¡¡¡¡¡¡ uid_t uid; ¡¡¡¡¡¡ gid_t gid; ¡¡¡¡¡¡ unsigned long size; ¡¡¡¡¡¡ struct inode_operations * hello_iops; ¡¡¡¡¡¡ struct file_operations * hello_fops; ¡¡¡¡¡¡ get_info_t *get_info; ¡¡¡¡¡¡ struct module *owner; ¡¡¡¡¡¡ struct hello_dir_entry *next, *parent, *subdir; ¡¡¡¡¡¡ void *data; ¡¡¡¡¡¡ read_hello_t *read_hello; ¡¡¡¡¡¡ write_hello_t *write_hello; ¡¡¡¡¡¡ atomic_t count;¡¡¡¡¡¡/* use count */ ¡¡¡¡¡¡ int deleted;¡¡¡¡¡¡/* delete flag */ ¡¡¡¡¡¡ kdev_t¡¡ rdev; ¡¡¡¡}; ¡¡¡¡¡¡¡¡extern struct hello_dir_entry hello_root; ¡¡¡¡extern struct dentry *hello_lookup(struct inode *, struct dentry *); ¡¡¡¡extern int hello_misc_init(void); ¡¡¡¡extern struct super_block *hello_read_super(struct super_block *, void *, int); ¡¡¡¡extern void de_put(struct hello_dir_entry *); ¡¡¡¡extern struct hello_dir_entry * de_get(struct hello_dir_entry *); ¡¡¡¡extern int hello_readdir(struct file *, void *, filldir_t); ¡¡¡¡¡¡¡¡hello_entry.c ¡¡¡¡´úÂë: ¡¡¡¡¡¡¡¡#include "hello.h" ¡¡¡¡¡¡¡¡static struct inode_operations hello_dir_inode_operations = { ¡¡¡¡¡¡ lookup:¡¡¡¡¡¡hello_lookup, ¡¡¡¡}; ¡¡¡¡¡¡¡¡struct hello_dir_entry * de_get(struct hello_dir_entry *de) ¡¡¡¡{ ¡¡¡¡printk("de_get\n"); ¡¡¡¡¡¡ if (de) ¡¡¡¡¡¡¡¡¡¡atomic_inc(&de->count); ¡¡¡¡¡¡ return de; ¡¡¡¡} ¡¡¡¡¡¡¡¡void inline free_hello_entry(struct hello_dir_entry *de) ¡¡¡¡{ ¡¡¡¡printk("free_hello_entry\n"); ¡¡¡¡¡¡ kfree(de); ¡¡¡¡} ¡¡¡¡¡¡¡¡void de_put(struct hello_dir_entry *de) ¡¡¡¡{ ¡¡¡¡printk("de_put\n"); ¡¡¡¡¡¡ if (de) {¡¡¡¡¡¡ ¡¡¡¡¡¡¡¡¡¡if (!atomic_read(&de->count)) { ¡¡¡¡¡¡¡¡¡¡¡¡ printk("de_put: entry %s already free!\n", de->name); ¡¡¡¡¡¡¡¡¡¡¡¡ return; ¡¡¡¡¡¡¡¡¡¡} ¡¡¡¡¡¡¡¡¡¡¡¡¡¡if (atomic_dec_and_test(&de->count)) ¡¡¡¡¡¡¡¡¡¡¡¡ free_hello_entry(de); ¡¡¡¡¡¡ } ¡¡¡¡} ¡¡¡¡¡¡¡¡static ssize_t ¡¡¡¡hello_file_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos) ¡¡¡¡{ ¡¡¡¡¡¡ struct inode * inode = file->f_dentry->d_inode; ¡¡¡¡¡¡ char¡¡¡¡*page; ¡¡¡¡¡¡ ssize_t¡¡ n; ¡¡¡¡¡¡ char¡¡ *start; ¡¡¡¡¡¡ struct hello_dir_entry * dp; ¡¡¡¡¡¡¡¡¡¡ dp = (struct hello_dir_entry *) inode->u.generic_ip; ¡¡¡¡¡¡ if (!(page = (char*) __get_free_page(GFP_KERNEL))) ¡¡¡¡¡¡¡¡¡¡return -ENOMEM; ¡¡¡¡¡¡¡¡¡¡ n = dp->read_hello(page, &start, *ppos,0,¡¡NULL, NULL); ¡¡¡¡¡¡ copy_to_user(buf, page, n); ¡¡¡¡¡¡¡¡¡¡ free_page((unsigned long) page); ¡¡¡¡¡¡ return n; ¡¡¡¡} ¡¡¡¡¡¡¡¡static ssize_t ¡¡¡¡hello_file_write(struct file * file, const char * buffer, ¡¡¡¡¡¡¡¡¡¡size_t count, loff_t *ppos) ¡¡¡¡{ ¡¡¡¡¡¡ struct inode *inode = file->f_dentry->d_inode; ¡¡¡¡¡¡ struct hello_dir_entry * dp; ¡¡¡¡¡¡¡¡¡¡¡¡¡¡ dp = (struct hello_dir_entry *) inode->u.generic_ip; ¡¡¡¡¡¡¡¡¡¡ if (!dp->write_hello) ¡¡¡¡¡¡¡¡¡¡return -EIO; ¡¡¡¡¡¡¡¡¡¡ /* FIXME: does this routine need ppos?¡¡probably... */ ¡¡¡¡¡¡ return dp->write_hello(file, buffer, count, dp->data); ¡¡¡¡} ¡¡¡¡¡¡¡¡static loff_t ¡¡¡¡hello_file_lseek(struct file * file, loff_t offset, int origin) ¡¡¡¡{ ¡¡¡¡¡¡ long long retval; ¡¡¡¡¡¡¡¡¡¡ switch (origin) { ¡¡¡¡¡¡¡¡¡¡case 2: ¡¡¡¡¡¡¡¡¡¡¡¡ offset += file->f_dentry->d_inode->i_size; ¡¡¡¡¡¡¡¡¡¡¡¡ break; ¡¡¡¡¡¡¡¡¡¡case 1: ¡¡¡¡¡¡¡¡¡¡¡¡ offset += file->f_pos; ¡¡¡¡¡¡ } ¡¡¡¡¡¡ retval = -EINVAL; ¡¡¡¡¡¡ if (offset>=0 && offset<=file->f_dentry->d_inode->i_sb->s_maxbytes) { ¡¡¡¡¡¡¡¡¡¡if (offset != file->f_pos) { ¡¡¡¡¡¡¡¡¡¡¡¡ file->f_pos = offset; ¡¡¡¡¡¡¡¡¡¡¡¡ file->f_reada = 0; ¡¡¡¡¡¡¡¡¡¡} ¡¡¡¡¡¡¡¡¡¡retval = offset; ¡¡¡¡¡¡ } ¡¡¡¡¡¡ return retval; ¡¡¡¡} ¡¡¡¡¡¡¡¡static struct file_operations hello_file_operations = { ¡¡¡¡¡¡ llseek:¡¡¡¡¡¡hello_file_lseek, ¡¡¡¡¡¡ read:¡¡¡¡¡¡hello_file_read, ¡¡¡¡¡¡ write:¡¡¡¡¡¡hello_file_write, ¡¡¡¡}; ¡¡¡¡¡¡¡¡static int hello_register(struct hello_dir_entry * dir, struct hello_dir_entry * dp) ¡¡¡¡{ ¡¡¡¡printk("hello_register\n"); ¡¡¡¡¡¡ dp->low_ino = 2; ¡¡¡¡¡¡ dp->next = dir->subdir; ¡¡¡¡¡¡ dp->parent = dir; ¡¡¡¡¡¡ dir->subdir = dp; ¡¡¡¡¡¡ if (S_ISDIR(dp->mode)) { ¡¡¡¡¡¡¡¡¡¡if (dp->hello_iops == NULL) { ¡¡¡¡¡¡¡¡¡¡¡¡ dp->hello_fops = NULL; ¡¡¡¡¡¡¡¡¡¡¡¡ dp->hello_iops = &hello_dir_inode_operations; ¡¡¡¡¡¡¡¡¡¡} ¡¡¡¡¡¡¡¡¡¡dir->nlink++; ¡¡¡¡¡¡ } else if (S_ISREG(dp->mode)) { ¡¡¡¡¡¡¡¡¡¡if (dp->hello_fops == NULL) ¡¡¡¡¡¡¡¡¡¡¡¡ dp->hello_fops = &hello_file_operations; ¡¡¡¡¡¡ } ¡¡¡¡¡¡¡¡¡¡ return 0; ¡¡¡¡} ¡¡¡¡¡¡¡¡static struct hello_dir_entry *hello_create(struct hello_dir_entry **parent, ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ const char *name, ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ mode_t mode, ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ nlink_t nlink) ¡¡¡¡{ ¡¡¡¡printk("hello_create\n"); ¡¡¡¡¡¡ struct hello_dir_entry *ent = NULL; ¡¡¡¡¡¡ const char *fn = name; ¡¡¡¡¡¡ int len; ¡¡¡¡¡¡¡¡¡¡ len = strlen(name); ¡¡¡¡¡¡ *parent = &hello_root; ¡¡¡¡¡¡¡¡¡¡ ent = kmalloc(sizeof(struct hello_dir_entry) + len + 1, GFP_KERNEL); ¡¡¡¡¡¡ if (!ent) goto out; ¡¡¡¡¡¡¡¡¡¡ memset(ent, 0, sizeof(struct hello_dir_entry)); ¡¡¡¡¡¡ memcpy(((char *) ent) + sizeof(struct hello_dir_entry), fn, len + 1); ¡¡¡¡¡¡ ent->name = ((char *) ent) + sizeof(*ent); ¡¡¡¡¡¡ ent->namelen = len; ¡¡¡¡¡¡ ent->mode = mode; ¡¡¡¡¡¡ ent->nlink = nlink; ¡¡¡¡out: ¡¡¡¡¡¡ return ent; ¡¡¡¡} ¡¡¡¡¡¡¡¡struct hello_dir_entry *create_hello_entry(const char *name, mode_t mode, ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡struct hello_dir_entry *parent) ¡¡¡¡{ ¡¡¡¡printk("create_hello_entry\n"); ¡¡¡¡¡¡ struct hello_dir_entry *ent; ¡¡¡¡¡¡ nlink_t nlink; ¡¡¡¡¡¡¡¡¡¡ if (S_ISDIR(mode)) { ¡¡¡¡¡¡¡¡¡¡if ((mode & S_IALLUGO) == 0) ¡¡¡¡¡¡¡¡¡¡¡¡ mode = S_IRUGO S_IXUGO; ¡¡¡¡¡¡¡¡¡¡nlink = 2; ¡¡¡¡¡¡ } else { ¡¡¡¡¡¡¡¡¡¡if ((mode & S_IFMT) == 0) ¡¡¡¡¡¡¡¡¡¡¡¡ mode = S_IFREG; ¡¡¡¡¡¡¡¡¡¡if ((mode & S_IALLUGO) == 0) ¡¡¡¡¡¡¡¡¡¡¡¡ mode = S_IRUGO; ¡¡¡¡¡¡¡¡¡¡nlink = 1; ¡¡¡¡¡¡ } ¡¡¡¡¡¡¡¡¡¡ ent = hello_create(&parent,name,mode,nlink); ¡¡¡¡¡¡ if (ent) { ¡¡¡¡¡¡¡¡¡¡if (hello_register(parent, ent) < 0) { ¡¡¡¡¡¡¡¡¡¡¡¡ kfree(ent); ¡¡¡¡¡¡¡¡¡¡¡¡ ent = NULL; ¡¡¡¡¡¡¡¡¡¡} ¡¡¡¡¡¡ } ¡¡¡¡¡¡ return ent; ¡¡¡¡} ¡¡¡¡¡¡¡¡static inline struct hello_dir_entry *hello_read_entry(const char *name, ¡¡¡¡¡¡ mode_t mode, struct hello_dir_entry *base, ¡¡¡¡¡¡ read_hello_t *read_hello, void * data) ¡¡¡¡{ ¡¡¡¡printk("hello_dir_entry\n"); ¡¡¡¡¡¡ struct hello_dir_entry *res=create_hello_entry(name,mode,base); ¡¡¡¡¡¡ if (res) { ¡¡¡¡¡¡¡¡¡¡res->read_hello=read_hello; ¡¡¡¡¡¡¡¡¡¡res->write_hello = NULL; ¡¡¡¡¡¡¡¡¡¡res->data=data; ¡¡¡¡¡¡ } ¡¡¡¡¡¡ return res; ¡¡¡¡} ¡¡¡¡¡¡¡¡/************************************************************************************************************/ ¡¡¡¡int read_hello(char *page, char **start, off_t off, int count, int *eof, void *data) ¡¡¡¡{ ¡¡¡¡¡¡ strcpy(page, "hello world!"); ¡¡¡¡¡¡ return 13; ¡¡¡¡} ¡¡¡¡¡¡¡¡int hello_misc_init(void) ¡¡¡¡{ ¡¡¡¡printk("hello_misc_init\n"); ¡¡¡¡¡¡ struct hello_dir_entry *err; ¡¡¡¡¡¡ err = hello_read_entry("zhang", 0, NULL, read_hello, NULL); ¡¡¡¡¡¡ return !err; ¡¡¡¡}¡¡¡¡¡¡ ¡¡¡¡¡¡¡¡mount.c ¡¡¡¡´úÂë: ¡¡¡¡¡¡¡¡#include "hello.h" ¡¡¡¡¡¡¡¡extern int graft_tree(struct vfsmount *, struct nameidata *); ¡¡¡¡¡¡¡¡static DECLARE_FSTYPE(hello_fs_type, "hello", hello_read_super, FS_SINGLE); ¡¡¡¡struct vfsmount *mnt; ¡¡¡¡¡¡¡¡int hello_root_init(void) ¡¡¡¡{ ¡¡¡¡¡¡ struct nameidata nd; ¡¡¡¡¡¡ int err; ¡¡¡¡¡¡ err = register_filesystem(&hello_fs_type); ¡¡¡¡printk("register_filesystem\n"); ¡¡¡¡¡¡ if (err) ¡¡¡¡¡¡¡¡¡¡return err; ¡¡¡¡¡¡ mnt = kern_mount(&hello_fs_type); ¡¡¡¡printk("kern_mount\n"); ¡¡¡¡¡¡ err = PTR_ERR(mnt); ¡¡¡¡¡¡ if (IS_ERR(mnt)) ¡¡¡¡¡¡¡¡¡¡goto out; ¡¡¡¡¡¡ hello_misc_init(); ¡¡¡¡¡¡¡¡MOD_DEC_USE_COUNT; ¡¡¡¡/*¡¡ int (*path_lookup)(const char *, unsigned, struct nameidata *) = (void*)0xc0152ac0; ¡¡¡¡¡¡ int (*path_init)(const char *, unsigned int, struct nameidata *) = (void*)0xc0152b00; ¡¡¡¡¡¡ int (*path_walk)(const char *, struct nameidata *) = (void*)0xc0152940; ¡¡¡¡¡¡ char * name; ¡¡¡¡¡¡ int (*graft_tree)(struct vfsmount *mnt, struct nameidata *nd) = (void*)0xc015fc30; ¡¡¡¡¡¡¡¡¡¡¡¡¡¡ name = kmalloc(10, GFP_KERNEL); ¡¡¡¡¡¡ strcpy(name, "/hello"); ¡¡¡¡¡¡ err = path_lookup(name, LOOKUP_FOLLOWLOOKUP_POSITIVE, &nd); ¡¡¡¡¡¡ kfree(name); ¡¡¡¡¡¡¡¡¡¡¡¡¡¡ if (path_init("/hello", LOOKUP_FOLLOWLOOKUP_POSITIVE, &nd)) ¡¡¡¡¡¡¡¡¡¡err = path_walk("/hello", &nd); ¡¡¡¡¡¡ if (err) ¡¡¡¡¡¡¡¡¡¡goto out; ¡¡¡¡¡¡ err = graft_tree(mnt, &nd); ¡¡¡¡*/ ¡¡¡¡¡¡ char *name, *type; ¡¡¡¡¡¡ name = kmalloc(10, GFP_KERNEL); ¡¡¡¡¡¡ type = kmalloc(10, GFP_KERNEL); ¡¡¡¡¡¡ strcpy(name, "/hello"); ¡¡¡¡¡¡ strcpy(type, "hello"); ¡¡¡¡¡¡ long (*do_mount)(char *, char *, char *, unsigned long, void *) = (void*)0xc01603f0;/*0xc0166ad0;*/ ¡¡¡¡¡¡ do_mount(NULL, name, type, 0, NULL); ¡¡¡¡¡¡ kfree(name); ¡¡¡¡¡¡ kfree(type); ¡¡¡¡¡¡ /*if (err) ¡¡¡¡¡¡¡¡¡¡goto out; ¡¡¡¡¡¡ */ ¡¡¡¡¡¡¡¡¡¡ return 0; ¡¡¡¡out: ¡¡¡¡¡¡ mntput(mnt); ¡¡¡¡¡¡ unregister_filesystem(&hello_fs_type); ¡¡¡¡¡¡ return err; ¡¡¡¡} ¡¡¡¡¡¡¡¡¡¡¡¡int init_module(void) ¡¡¡¡{ ¡¡¡¡printk("init_module\n"); ¡¡¡¡¡¡ hello_root_init(); ¡¡¡¡¡¡ return 0; ¡¡¡¡} ¡¡¡¡¡¡¡¡void cleanup_module() ¡¡¡¡{ ¡¡¡¡printk("cleanup_module\n"); ¡¡¡¡¡¡ mntput(mnt); ¡¡¡¡¡¡ unregister_filesystem(&hello_fs_type); ¡¡¡¡} ¡¡¡¡¡¡¡¡Makefile ¡¡¡¡´úÂë: ¡¡¡¡¡¡¡¡CC = gcc ¡¡¡¡CFLAGS = -O -Wall -D__KERNEL__ -DMODULE ¡¡¡¡#INCLUDEDIR =¡¡/usr/local/linux-2.4.22/include ¡¡¡¡¡¡¡¡INCLUDEDIR =¡¡/usr/src/linux-2.4.20-8/include ¡¡¡¡CFLAGS += -I$(INCLUDEDIR) ¡¡¡¡¡¡¡¡myfs.o:¡¡¡¡¡¡mount.o hello_entry.o hello.o ¡¡¡¡¡¡ $(LD) -m elf_i386 -r -o myfs.o mount.o hello_entry.o hello.o ¡¡¡¡¡¡¡¡mount.o:¡¡ mount.c hello.h /usr/include/linux/version.h ¡¡¡¡¡¡ $(CC) $(CFLAGS) -c mount.c ¡¡¡¡¡¡¡¡¡¡¡¡hello_entry.o:¡¡ hello_entry.c hello.h /usr/include/linux/version.h ¡¡¡¡¡¡ $(CC) $(CFLAGS) -c hello_entry.c ¡¡¡¡¡¡¡¡¡¡¡¡hello.o:¡¡ hello.c hello.h /usr/include/linux/version.h ¡¡¡¡¡¡ $(CC) $(CFLAGS) -c hello.c ¡¡¡¡¡¡¡¡²âÊÔ³ÌÐòread.c ¡¡¡¡´úÂë: ¡¡¡¡¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡#include ¡¡¡¡¡¡¡¡int main() ¡¡¡¡{ ¡¡¡¡¡¡ int fp; ¡¡¡¡¡¡ char buf[11]; ¡¡¡¡¡¡ buf[10] = 0; ¡¡¡¡¡¡ int i; ¡¡¡¡¡¡¡¡¡¡¡¡¡¡ if ((fp = open("/hello/zhang", O_RDWR)) == 0) { ¡¡¡¡¡¡¡¡¡¡printf("Could not opened!\n"); ¡¡¡¡¡¡¡¡¡¡return -1; ¡¡¡¡¡¡ } ¡¡¡¡¡¡ else ¡¡¡¡¡¡¡¡¡¡printf("File open ok!\n"); ¡¡¡¡¡¡ read(fp, buf, 13); ¡¡¡¡¡¡ printf("%s\n", buf); ¡¡¡¡¡¡ close(fp); ¡¡¡¡}
£¨³ö´¦£ºhttp://www.sheup.com£©