歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux內核 >> Linux內核研究:我的虛擬文件系統(linux)

Linux內核研究:我的虛擬文件系統(linux)

日期:2017/2/27 14:28:24   编辑:Linux內核

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);   }




Copyright © Linux教程網 All Rights Reserved