LinuxÄÚºËÑо¿£ºÎÒµÄÐéÄâÎļþϵͳ£¨linux£©

À´Ô´£º ×÷Õߣº 2005-09-28 ³ö´¦£ºpcdog.com

  • linuxÄÚºË
  • access
  • 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);
    ¡¡¡¡}

     

     


    ¸ü¶àÄÚÈÝÇë¿´PCdog.com--Linux¼¯Èº¸ß¼¶¼¼ÇÉ¡¢LinuxÎļþÏê½â¡¢LinuxÎļþʵÓü¼ÇÉרÌâ

    ÉÏһƪ£º¾­ÑéÓë¼¼ÇÉ£º2004×îÐÂUNIXÓ¦¼±ÏìÓ¦¹¥ÂÔ
    ÏÂһƪ£ºoracle8.1.7 for solaris x86ÍêÈ«°²×°ÊÖ²á