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_FOLLOW|LOOKUP_POSITIVE, &nd); 
¡¡¡¡¡¡ kfree(name); 
¡¡¡¡¡¡¡¡
¡¡¡¡¡¡ if (path_init("/hello", LOOKUP_FOLLOW|LOOKUP_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); 
¡¡¡¡}
                  	
				

bourne1209 ÓÚ 2009-03-23 18:32:33·¢±í:
ÏÖÔÚ¿´²»´ó¶®Èö£¬µÃŬÁ¦Á˺Ç:0w5ty(1