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