- 论坛徽章:
- 0
|
不知道该不该发这里,是我从proc改来的,懂内核源码的交流交流
hello.c
- #include "hello.h"
- struct inode * hello_get_inode(struct super_block *, int, struct hello_dir_entry *);
- /*这个函数是直接从linux复制过来的,作用就是显示目录里的文件名,没有这个
- 函数也行只是你用ls、dir命令看不到目录下的文件。*/
- 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*/
- };
- /*读文件节点,这个函数是被real_lookup函数调用的,具体调用是这里dir->;i_op->;lookup(dir, dentry);作用是从磁盘读文件节点填充inode结构。我这里用hello_dir_entry结构填充的*/
- 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,
- };
- /*填充inode结构*/
- 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);
- }
- /*创建根目录的dentry结构*/
- 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);/*把根目录的inode结构安装到dentry结构里*/
- }
- }
- 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 <linux/kernel.h>;
- #include <linux/module.h>;
- #include <linux/fs.h>;
- #include <linux/wrapper.h>;
- #include <linux/slab.h>;
- #include <linux/wait.h>;
- #include <linux/poll.h>;
- #include <linux/mm.h>;
- #include <linux/pagemap.h>;
- #include <asm/uaccess.h>;
- #include <asm/semaphore.h>;
- #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"
- /*加载模块并安装文件系统*/
- 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;
- 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 <sys/ioctl.h>;
- #include <sys/types.h>;
- #include <sys/stat.h>;
- #include <fcntl.h>;
- 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);
- }
复制代码 |
|