说明:本文基于Linux2.6内核分析;其他内核版本仅供参考。 前边通过源码情景分析,看过了总线、设备、驱动及其发现机制,Linux2.6内核udev设备节点创建相关;对于文件系统,一直望而生畏,但内核学习、这部分又不可能绕的过去。目前对VFS中使用的hash表还未做研究,它在dentry和vfsmount下查找节点起关键作用;后边在做分析。下边将根文件系统挂载过程做简单分析: 一、rootfs的诞生 引子: Linux一切皆文件的提出:在Linux中,普通文件、目录、字符设备、块设备、套接字等都以文件被对待;他们具体的类型及其操作不同,但需要向上层提供统一的操作接口。 虚拟文件系统VFS就是Linux内核中的一个软件层,向上给用户空间程序提供文件系统操作接口;向下允许不同的文件系统共存。所以,所有实际文件系统都必须实现VFS的结构封装。 矛盾的提出: Linux系统中任何文件系统的挂载必须满足两个条件:挂载点和文件系统。 直接挂载nfs或flash文件系统有如下两个问题必须解决: 1.谁来提供挂载点?我们可以想象自己创建一个超级块(包含目录项和i节点),这时挂载点不是就有了吗;很可惜,linux引入VFS(一切皆文件,所有类型文件系统必须提供一个VFS的软件层、以向上层提供统一接口)后该问题不能这么解决,因为挂载点必须关联到文件系统、也就是说挂载点必须属于某个文件系统。 2.怎样访问到nfs或flash上的文件系统?我们可以说直接访问设备驱动读取其上边的文件系统(设备上的文件系统是挂载在自己的根目录),不就可以了吗;别忘了还是Linux的VFS,设备访问也不例外。因为访问设备还是需要通过文件系统来访问它的挂载点,不能直接访问(要满足Linux的VFS架构,一切皆文件)。 所以,一句话:rootfs之所以存在,是因为需要在VFS机制下给系统提供最原始的挂载点。 如此矛盾,需要我们引入一种特殊文件系统: 1.它是系统自己创建并加载的第一个文件系统;该文件系统的挂载点就是它自己的根目录项。 2.该文件系统不能存在于nfs或flash上,因为如此将会陷入之前的矛盾。 rootfs的诞生: 上述问题需要我们创建具有如下三个特点的特殊文件系统: 1.它是系统自己创建并加载的第一个文件系统; 2.该文件系统的挂载点就是它自己的根目录项对象; 3.该文件系统仅仅存在于内存中。 由以上分析可以看出,rootfs是Linux的VFS(一切皆文件,所有类型文件系统必须提供一个VFS的软件层、以向上层提供统一接口)存在的基石;二者关系密切。如果没有VFS机制,rootfs也就没有存在的必要;同样,如果没有rootfs、VFS机制也就不能实现。 这就是两者之间的真正关系,之前看网上什么说法都有:有的只说关系密切,没有指明具体关系;有的干脆误人子弟,说VFS就是rootfs。 其实,VFS是一种机制、是Linux下每一种文件系统(包括刚才说的rootfs,还有常见的ext3、yaffs等)都必须按照这个机制去实现的一种规范;而rootfs仅仅是符合VFS规范的而且又具有如上3个特点的一个文件系统。 VFS是Linux文件系统实现必须遵循的一种机制,rootfs是一种具体实现的文件系统、Linux下所有文件系统的实现都必须符合VFS的机制(符合VFS的接口);这就是二者的真正关系。 以下分析基于Android模拟器Linux2.6.29内核: 二、相关数据结构 Linux内核中current指针作为全局变量,使用非常广泛;例如:进程上下文中获取当前进程ID、任务调度,以及open等文件系统调用中路径搜索等;首先介绍下current结构体: 各个平台、各个内核版本中current的实现可能不同;但原理是一样的。该指针一般定义在具体平台的current.h头文件中,类型为struct task_struct: #define current (get_current()) static inline struct task_struct *get_current(void) include/linux/sched.h struct task_struct { ...... struct thread_info *thread_info; struct list_head tasks; pid_t pid; pid_t tgid; uid_t uid,euid,suid,fsuid; gid_t gid,egid,sgid,fsgid; struct fs_struct *fs; //本节将大量使用这个 struct files_struct *files; ...... } 1.文件系统注册 kernel/include/include/fs.h struct file_system_type { const char *name; //文件系统名字;如:rootfs及ext3等 int fs_flags; int (*get_sb) (struct file_system_type *, int, const char *, void *, struct vfsmount *); //安装/挂载文件系统时,会调用;获取超级块。 void (*kill_sb) (struct super_block *); //卸载文件系统时会调用。 struct module *owner; struct file_system_type * next; //指向下一个文件系统类型。 struct list_head fs_supers; //同一个文件系统类型中所有超级块组成双向链表。 struct lock_class_key s_lock_key; struct lock_class_key s_umount_key; struct lock_class_key i_lock_key; struct lock_class_key i_mutex_key; struct lock_class_key i_mutex_dir_key; struct lock_class_key i_alloc_sem_key; }; 2.文件系统挂载vfsmount(struct vfsmount): 本质上,mount操作的过程就是新建一个vfsmount结构,然后将此结构和挂载点(目录项对象)关联。关联之后,目录查找时就能沿着vfsmount挂载点一级级向下查找文件了。 对于每一个mount的文件系统,都由一个vfsmount实例来表示。 kernel/include/linux/mount.h struct vfsmount { struct list_head mnt_hash; //内核通过哈希表对vfsmount进行管理 struct vfsmount *mnt_parent;//指向父文件系统对应的vfsmount struct dentry *mnt_mountpoint; //指向该文件系统挂载点对应的目录项对象dentry struct dentry *mnt_root; //该文件系统对应的设备根目录dentry struct super_block *mnt_sb; //指向该文件系统对应的超级块 struct list_head mnt_mounts; struct list_head mnt_child; //同一个父文件系统中的所有子文件系统通过该字段链接成双联表 int mnt_flags; /* 4 bytes hole on 64bits arches */ const char *mnt_devname;/* Name of device e.g. /dev/dsk/hda1 */ struct list_head mnt_list; //所有已挂载文件系统的vfsmount结构通过该字段链接在一起 struct list_head mnt_expire;/* link in fs-specific expiry list */ struct list_head mnt_share;/* circular list of shared mounts */ struct list_head mnt_slave_list;/* list of slave mounts */ struct list_head mnt_slave;/* slave list entry */ struct vfsmount *mnt_master;/* slave is on master->mnt_slave_list */ struct mnt_namespace *mnt_ns;/* containing namespace */ int mnt_id;/* mount identifier */ int mnt_group_id;/* peer group identifier */ /* * We put mnt_count & mnt_expiry_mark at the end of struct vfsmount * to let these frequently modified fields in a separate cache line * (so that reads of mnt_flags wont ping-pong on SMP machines) */ atomic_t mnt_count; int mnt_expiry_mark;/* true if marked for expiry */ int mnt_pinned; int mnt_ghosts; /* * This value is not stable unless all of the mnt_writers[] spinlocks * are held, and all mnt_writer[]s on this mount have 0 as their ->count */ atomic_t __mnt_writers; }; 3.超级块(struct super_bloc): kernel/include/linux/fs.h struct super_block { struct list_heads_list;/* Keep this first */ dev_ts_dev;/* search index; _not_ kdev_t */ unsigned longs_blocksize; unsigned chars_blocksize_bits; unsigned chars_dirt; unsigned long longs_maxbytes;/* Max file size */ struct file_system_type*s_type; //文件系统类型 //(kernel/include/linux/fs.h,struct file_system_type) const struct super_operations*s_op; struct dquot_operations*dq_op; struct quotactl_ops*s_qcop; const struct export_operations *s_export_op; unsigned longs_flags; unsigned longs_magic; struct dentry*s_root; //超级块要指向目录项对象 struct rw_semaphores_umount; struct mutexs_lock; ints_count; ints_need_sync_fs; atomic_ts_active; #ifdef CONFIG_SECURITY void *s_security; #endif struct xattr_handler**s_xattr; struct list_heads_inodes;/* all inodes */ struct list_heads_dirty;/* dirty inodes */ struct list_heads_io;/* parked for writeback */ struct list_heads_more_io;/* parked for more writeback */ struct hlist_heads_anon;//哈希表头/* anonymous dentries for (nfs) exporting */ struct list_heads_files; /* s_dentry_lru and s_nr_dentry_unused are protected by dcache_lock */ struct list_heads_dentry_lru;/* unused dentry lru */ ints_nr_dentry_unused;/* # of dentry on lru */ struct block_device*s_bdev; struct mtd_info*s_mtd; struct list_heads_instances; struct quota_infos_dquot;/* Diskquota specific options */ ints_frozen; wait_queue_head_ts_wait_unfrozen; char s_id[32];/* Informational name */ void *s_fs_info;/* Filesystem private info */ fmode_ts_mode; /* * The next field is for VFS *only*. No filesystems have any business * even looking at it. You had been warned. */ struct mutex s_vfs_rename_mutex;/* Kludge */ /* Granularity of c/m/atime in ns.Cannot be worse than a second */ u32 s_time_gran; /* * Filesystem subtype. If non-empty the filesystem type field * in /proc/mounts will be 'type.subtype' */ char *s_subtype; /* * Saved mount options for lazy filesystems using * generic_show_options() */ char *s_options; /* * storage for asynchronous operations */ struct list_head s_async_list; }; 4.目录索引节点(struct inode): kernel/include/linux/fs.h struct inode { struct hlist_nodei_hash; //哈希表节点 struct list_headi_list; struct list_headi_sb_list; struct list_headi_dentry; unsigned longi_ino; atomic_ti_count; unsigned inti_nlink; uid_ti_uid; gid_ti_gid; dev_ti_rdev; u64i_version; loff_ti_size; #ifdef __NEED_I_SIZE_ORDERED seqcount_ti_size_seqcount; #endif struct timespeci_atime; struct timespeci_mtime; struct timespeci_ctime; unsigned inti_blkbits; blkcnt_ti_blocks; unsigned short i_bytes; umode_ti_mode; spinlock_ti_lock;/* i_blocks, i_bytes, maybe i_size */ struct mutexi_mutex; struct rw_semaphorei_alloc_sem; const struct inode_operations*i_op; const struct file_operations*i_fop;/* former ->i_op->default_file_ops */ struct super_block*i_sb; struct file_lock*i_flock; struct address_space*i_mapping; struct address_spacei_data; #ifdef CONFIG_QUOTA struct dquot*i_dquot[MAXQUOTAS]; #endif struct list_headi_devices; union { struct pipe_inode_info*i_pipe; struct block_device*i_bdev; struct cdev*i_cdev; }; inti_cindex; __u32i_generation; #ifdef CONFIG_DNOTIFY unsigned longi_dnotify_mask; /* Directory notify events */ struct dnotify_struct*i_dnotify; /* for directory notifications */ #endif #ifdef CONFIG_INOTIFY struct list_headinotify_watches; /* watches on this inode */ struct mutexinotify_mutex;/* protects the watches list */ #endif unsigned longi_state; unsigned longdirtied_when;/* jiffies of first dirtying */ unsigned inti_flags; atomic_ti_writecount; #ifdef CONFIG_SECURITY void*i_security; #endif void*i_private; /* fs or device private pointer */ }; 5.目录项对象(struct dentry): kernel/include/linux/dcache.h struct dentry { atomic_t d_count; unsigned int d_flags;/* protected by d_lock */ spinlock_t d_lock;/* per dentry lock */ int d_mounted; struct inode *d_inode; //目录项对象与目录索引的关联 /* Where the name belongs to - NULL is * negative */ /* * The next three fields are touched by __d_lookup. Place them here * so they all fit in a cache line. */ struct hlist_node d_hash; //哈希表节点/* lookup hash list */ struct dentry *d_parent; //目录项对象的父亲/* parent directory */ struct qstr d_name; //d_name.name这个是文件名,目录对象与目录名的关联 struct list_head d_lru;/* LRU list */ /* * d_child and d_rcu can share memory */ union { struct list_head d_child;/* child of parent list */ struct rcu_head d_rcu; } d_u; struct list_head d_subdirs;/* our children */ struct list_head d_alias;/* inode alias list */ unsigned long d_time;/* used by d_revalidate */ struct dentry_operations *d_op; struct super_block *d_sb; //指向文件系统的超级块/* The root of the dentry tree */ void *d_fsdata;/* fs-specific data */ unsigned char d_iname[DNAME_INLINE_LEN_MIN];/* small names */ }; 其他: include/linux/fs.h struct file { /* * fu_list becomes invalid after file_free is called and queued via * fu_rcuhead for RCU freeing */ union { struct list_headfu_list; struct rcu_head fu_rcuhead; } f_u; struct pathf_path; //重要!!!记录挂载信息和目录项信息 #define f_dentryf_path.dentry #define f_vfsmntf_path.mnt const struct file_operations*f_op; atomic_long_tf_count; unsigned int f_flags; fmode_tf_mode; loff_tf_pos; struct fown_structf_owner; const struct cred*f_cred; struct file_ra_statef_ra; u64f_version; #ifdef CONFIG_SECURITY void*f_security; #endif /* needed for tty driver, and maybe others */ void*private_data; #ifdef CONFIG_EPOLL /* Used by fs/eventpoll.c to link all the hooks to this file */ struct list_headf_ep_links; spinlock_tf_ep_lock; #endif /* #ifdef CONFIG_EPOLL */ struct address_space*f_mapping; #ifdef CONFIG_DEBUG_WRITECOUNT unsigned long f_mnt_write_state; #endif }; include/linux/fs_struct.h struct fs_struct { atomic_t count; rwlock_t lock; int umask; struct path root, pwd; //重要!!!记录挂载信息和目录项信息 }; include/linux/namei.h struct nameidata { struct pathpath; //重要!!!记录挂载信息和目录项信息 struct qstrlast; //重要!!!记录目录名 unsigned intflags; intlast_type; unsigneddepth; char *saved_names[MAX_NESTED_LINKS + 1]; /* Intent data */ union { struct open_intent open; } intent; }; include/linux/path.h struct path { struct vfsmount *mnt; //重要!!!记录文件系统挂载信息 struct dentry *dentry; //重要!!!记录目录项信息 }; include/linux/dcache.h struct qstr { unsigned int hash; unsigned int len; const unsigned char *name;//重要!!!目录/文件名字,如'/','tank1'等具体的文件名 }; 三、注册/创建、安装/挂载rootfs,并调用set_fs_root设置系统current的根文件系统为rootfs 过程: 第一步:建立rootfs文件系统; 第二步:调用其get_sb函数(对于rootfs这种内存/伪文件系统是get_sb_nodev,实际文件系统比如ext2等是get_sb_bdev)、建立超级块(包含目录项和i节点); 第三步:挂载该文件系统(该文件系统的挂载点指向该文件系统超级块的根目录项); 第四步:将系统current的根文件系统和根目录设置为rootfs和其根目录。 kernel/init/main.c asmlinkage void __init start_kernel(void) { setup_arch(&command_line);//解析uboot命令行,实际文件系统挂载需要 parse_args('Booting kernel', static_command_line, __start___param, __stop___param - __start___param, &unknown_bootoption); vfs_caches_init(num_physpages); } kernel/fs/dcache.c void __init vfs_caches_init(unsigned long mempages) { mnt_init(); bdev_cache_init(); //块设备文件创建 chrdev_init();//字符设备文件创建 } kernel/fs/namespace.c void __init mnt_init(void) { init_rootfs(); //向内核注册rootfs init_mount_tree();//重要!!!rootfs根目录的建立以及rootfs文件系统的挂载;设置系统current根目录和根文件系统为rootfs } 下边分两步: 1.向内核注册rootfs虚拟文件系统init_rootfs kernel/fs/ramfs/inode.cint __init init_rootfs(void) { err = register_filesystem(&rootfs_fs_type); } static struct file_system_type rootfs_fs_type = { .name= 'rootfs', .get_sb= rootfs_get_sb, .kill_sb= kill_litter_super, }; 2.建立rootfs的根目录,并将rootfs挂载到自己的根目录;设置系统current根目录和根文件系统 kernel/fs/namespace.cstatic void __init init_mount_tree(void) { struct vfsmount *mnt; struct mnt_namespace *ns; struct path root; //创建rootfs的vfsmount结构,建立rootfs的超级块、并将rootfs挂载到自己的根目录。 /* mnt->mnt_mountpoint = mnt->mnt_root = dget(sb->s_root),而该mnt和自己的sb是关联的; 所以,是把rootfs文件系统挂载到了自己对应的超级块的根目录上。 这里也是实现的关键:一般文件系统的挂载是调用do_mount->do_new_mount而该函数中首先调用do_kern_mount,这时mnt->mnt_mountpoint = mnt->mnt_root;但后边 它还会调用do_add_mount->graft_tree->attach_recursive_mnt如下代码mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt)改变了其挂载点!!! */ mnt = do_kern_mount('rootfs', 0, 'rootfs', NULL); list_add(&mnt->mnt_list, &ns->list); ns->root = mnt; //将创建好的mnt加入系统当前 mnt->mnt_ns = ns; init_task.nsproxy->mnt_ns = ns; //设置进程的命名空间 get_mnt_ns(ns); root.mnt = ns->root; //文件系统为rootfs,相当与root.mnt = mnt; root.dentry = ns->root->mnt_root;//目录项为根目录项,相当与root.dentry = mnt->mnt_root; //设置系统current的pwd目录和文件系统 set_fs_pwd(current->fs, &root); //设置系统current根目录,根文件系统。这个是关键!!!整个内核代码最多只有两处调用 set_fs_root(current->fs, &root); } 以下着重分析do_kern_mount函数,它实现了rootfs在自己根目录上的挂载: kernel/fs/super.cstruct vfsmount * do_kern_mount(const char *fstype, int flags, const char *name, void *data) { mnt = vfs_kern_mount(type, flags, name, data); return mnt; } kernel/fs/super.c struct vfsmount * vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) { mnt = alloc_vfsmnt(name); //建立并填充vfsmount error = type->get_sb(type, flags, name, data, mnt);//为文件系统建立并填充超级块(主要是其dentry和inode),建立rootfs根目录 mnt->mnt_mountpoint = mnt->mnt_root; //文件系统挂载点目录,其实就是刚才建立的”/”目录。挂载点就是自己!!!! mnt->mnt_parent = mnt; //父对象是自己!!!! return mnt; }kernel/fs/ramfs/inode.cstatic int rootfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super, mnt); } kernel/fs/super.c int get_sb_nodev(struct file_system_type *fs_type, int flags, void *data, int (*fill_super)(struct super_block *, void *, int), struct vfsmount *mnt) { struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); //在内存中分配一个超级块 error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); //执行回调,填充超级块,并建立根目录项及对应i节点 /* kernel/fs/ramfs/inode.c static int ramfs_fill_super(struct super_block * sb, void * data, int silent) { struct inode * inode; struct dentry * root; sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = RAMFS_MAGIC; sb->s_op = &ramfs_ops; //static const struct super_operations ramfs_ops; sb->s_time_gran = 1; //建立根目录索引节点,我们最终的目标是要找到目录项对象关联的索引节点。 //根目录索引节点会有自己的ops。 inode = ramfs_get_inode(sb, S_IFDIR | 0755, 0); //ramfs_get_inode kernel/fs/ramfs/inode.c struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev) { struct inode * inode = new_inode(sb); switch (mode & S_IFMT) { //判断文件类型 default: init_special_inode(inode, mode, dev); //init_special_inode void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev) { inode->i_mode = mode; if (S_ISCHR(mode)) {//字符设备文件 inode->i_fop = &def_chr_fops; inode->i_rdev = rdev; } else if (S_ISBLK(mode)) {//块设备文件 inode->i_fop = &def_blk_fops; inode->i_rdev = rdev; } else if (S_ISFIFO(mode)) inode->i_fop = &def_fifo_fops; else if (S_ISSOCK(mode)) //网络设备文件 inode->i_fop = &bad_sock_fops; else printk(KERN_DEBUG 'init_special_inode: bogus i_mode (%o) for' ' inode %s:%lu\n', mode, inode->i_sb->s_id, inode->i_ino); } //init_special_inode end break; case S_IFREG: //普通文件 inode->i_op = &ramfs_file_inode_operations; //索引节点的操作方法 inode->i_fop = &ramfs_file_operations; //缺省普通文件的操作方法 break; case S_IFDIR: //目录文件 inode->i_op = &ramfs_dir_inode_operations; //ramfs_dir_inode_operations static const struct inode_operations ramfs_dir_inode_operations; kernel/include/linux/fs.h struct inode_operations { int (*create) (struct inode *,struct dentry *,int, struct nameidata *); int (*mkdir) (struct inode *,struct dentry *,int); int (*rmdir) (struct inode *,struct dentry *); int (*mknod) (struct inode *,struct dentry *,int,dev_t); } //ramfs_dir_inode_operations end inode->i_fop = &simple_dir_operations; //目录文件的操作方法 inc_nlink(inode); break; } } //ramfs_get_inode end //建立根目录目录对象,目录项对象的存在主要是为了我们进行路径的查找。 root = d_alloc_root(inode); //d_alloc_root kernel/fs/dcache.c struct dentry * d_alloc_root(struct inode * root_inode) { struct dentry *res = NULL; static const struct qstr name = { .name = '/', .len = 1 }; res = d_alloc(NULL, &name); res->d_sb = root_inode->i_sb; //指向该文件系统的超级块 res->d_parent = res; //根目录的父亲是它自己 d_instantiate(res, root_inode); //关联 dentry 和 inode } //d_alloc_root end sb->s_root = root; //超级块的s_root指向刚建立的根目录对象。 } */ return simple_set_mnt(mnt, s); //关联超级块(包含目录项dentry和i节点inode)和vfsmount }kernel/fs/namespace.c int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb) { printk('TK-------_>>>>>>>namespace.c>>>>simple_set_mnt\n');//add by tankai mnt->mnt_sb = sb; //对 mnt_sb超级块指针附值 mnt->mnt_root = dget(sb->s_root); //对mnt_root指向的根目录赋值 return 0; } 至此,rootfs文件系统建立、并且挂载于自己超级块(包括目录项dentry和i节点inod)对应的目录项,设置了系统current根目录和根文件系统、pwd的目录和文件系统。 ======================================== 释放Initramfs到rootfs;如果Initramfs中有init,这种情况比较特殊、rootfs就是最后系统使用的根文件系统。 而且此时,不需要在单独烧录根文件系统的img;此时,根文件系统就是内核uImage的一部分。当然,缺陷就是该文件系统运行时的介质是ramdisk即内存盘、它不再与磁盘对应;因此,此时修改根目录下的文件将不被得到保存。它的内核配置项为:CONFIG_INITRAMFS_SOURCE。实际项目中会经常碰到。 make menuconfig->General setup->Initial RAM filesystem and RAM disk(initramfs/initrd) support 底下的Initramfs source file(s)填写根文件系统的路径,如:../out/target/product/tclm6/root;不填的话,将导致initrd或磁盘文件系统的挂载(因为下边将会看到,内核将找不到“/init”)。 对应内核源码: kernel/init/main.cstatic int __init kernel_init(void * unused){ ...... do_basic_setup(); //初始化设备驱动,加载静态内核模块;释放Initramfs到rootfs /* kernel/init/initramfs.c rootfs_initcall(populate_rootfs); static int __init populate_rootfs(void) { printk(KERN_INFO 'checking if image is initramfs...'); err = unpack_to_rootfs((char *)initrd_start, initrd_end - initrd_start, 1); //释放ramdisk到rootfs } */ ...... if (!ramdisk_execute_command) ramdisk_execute_command = '/init'; if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) { ramdisk_execute_command = NULL; //如果此时rootfs中没有init,则加载initfd、nfs或磁盘文件系统 //也即磁盘的文件系统挂载至rootfs的/root目录,并设置系统current对应的根目录项为磁盘根目录项、系统current根文件系统为磁盘文件系统 //至此,rootfs对于以后所有进程而言、已被隐藏。 prepare_namespace(); } init_post(); //启动init进程 ...... } 看看init_post实现: static noinline int init_post(void) { if (ramdisk_execute_command) { //Initramfs从这里启动init run_init_process(ramdisk_execute_command); printk(KERN_WARNING 'Failed to execute %s\n', ramdisk_execute_command); } //initrd、nfs和磁盘都是从如下启动的init if (execute_command) { run_init_process(execute_command); printk(KERN_WARNING 'Failed to execute %s. Attempting ' 'defaults...\n', execute_command); } //一般执行如下 run_init_process('/sbin/init'); run_init_process('/etc/init'); run_init_process('/bin/init'); run_init_process('/bin/sh'); } 四、挂载实际文件系统至rootfs,并调用set_fs_root设置为系统current的根文件系统 下边从uboot启动内核参数的角度来简单说明: 以下三种情况都是将文件系统挂载到rootfs的/root目录,并将系统current的根目录切换为/root、系统current的根文件系统切换为磁盘文件系统。 kernel/init/do_mounts.c void __init prepare_namespace(void) { if (initrd_load()) //如果挂载initrd并执行成功,则不再挂载磁盘文件系统 goto out; if (saved_root_name[0]) { root_device_name = saved_root_name; if (!strncmp(root_device_name, 'mtd', 3) || !strncmp(root_device_name, 'ubi', 3)) { mount_block_root(root_device_name, root_mountflags); //启动时root=参数,如《四.2》中“root=/dev/mtdblock0” goto out; } ROOT_DEV = name_to_dev_t(root_device_name); if (strncmp(root_device_name, '/dev/', 5) == 0) root_device_name += 5; } mount_root(); //将实际文件系统挂载到rootfs的/root目录 out: //sys_mount('.', '/', NULL, MS_MOVE, NULL); 这句话无关紧要,影响理解;屏蔽不影响功能 sys_chroot('.'); //将当前目录(/root)设置为系统current根目录,磁盘文件系统设置为系统current根文件系统。 } 下边分两步解释mount_root()和sys_chroot('.')调用: 1.将nfs或磁盘文件系统挂载至rootfs的/root目录(以磁盘为例) void __init mount_root(void) { if (mount_nfs_root()) //如果网络文件系统挂载成功,则nfs作为根文件系统 return; //挂载磁盘文件系统为根文件系统 //在rootfs中建立/dev/root设备文件 create_dev('/dev/root', ROOT_DEV); //在rootfs中建立/dev/root设备文件,也就是/dev/mtdblock0设备。 //挂载/dev/root到rootfs的/root目录 mount_block_root('/dev/root', root_mountflags); } void __init mount_block_root(char *name, int flags) { int err = do_mount_root(name, p, flags, root_mount_data); } static int __init do_mount_root(char *name, char *fs, int flags, void *data) { int err = sys_mount(name, '/root', fs, flags, data);//将/dev/root挂载到/root sys_chdir('/root'); //系统current->fs->pwd为当前目录/root ROOT_DEV = current->fs->pwd.mnt->mnt_sb->s_dev; return 0; } 2.将当前目录/root设置为系统current根目录,磁盘文件系统设置为系统current根文件系统 分析sys_chroot('.'):见Linux内核编程之C语言预处理功能与宏 fs/open.c SYSCALL_DEFINE1(chroot, const char __user *, filename) { struct path path; error = user_path_dir(filename, &path); //这才是完成切换的关键!!!!整个内核代码只有两处调用 set_fs_root(current->fs, &path); } 注意,如下情况:rootfs特殊文件系统没有被卸载,他只是隐藏在基于磁盘的根文件系统下了。 initrd作为根文件系统 setenv bootargs root=/dev/ram0 initrd=0x2800000,24M rootfstype=ext2 mem=64M console=ttyAMA0 参数说明: root:用来指定rootfs的位置。 rootfstype:用来指定文件系统的类型。 nfs作为根文件系统 setenv bootargs root=/dev/nfs nfsroot=192.168.1.7:/opt/yz/nfs,rw ip=192.168.1.160 mem=64M console=ttyAMA0 参数说明: nfsroot:文件系统在哪台主机的哪个目录下。 ip:指定系统启动之后网卡的ip地址。 flash作为根文件系统 setenv bootargs root=/dev/mtdblock0 mem=16M mtdparts=armflash.1:4M@0x400000(jffs2) macaddr=9854 rootfstype=jffs2 console=ttyAMA0 参数说明: mtdparts:根文件系统在flash中的位置。 总结:rootfs永远不会被卸载,它只是被隐藏了。在用户空间下,更多地情况是只能见到rootfs这棵大树的一叶,而且还是被安装过文件系统了的。 五、其他说明 至于在mirco2440下mount出的结果: rootfs on / type rootfs (rw) /dev/root on / type yaffs (rw,relatime) none on /proc type proc (rw,relatime) none on /sys type sysfs (rw,relatime) none on /proc/bus/usb type usbfs (rw,relatime) none on /dev type ramfs (rw,relatime) none on /dev/pts type devpts (rw,relatime,mode=622) tmpfs on /dev/shm type tmpfs (rw,relatime) none on /tmp type ramfs (rw,relatime) none on /var type ramfs (rw,relatime) 从log中体会一下这个过程: s3c2410-rtc s3c2410-rtc: setting system clock to 2006-04-16 22:15:34 UTC (1145225734) TK------->>>>>init/main.c>>>>>>kernel_init>>before>prepare_namespace ################################################################################################################## TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_sb->s_type->name is rootfs ################################################################################################################## ################################################################################################################## TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_sb->s_type->name is rootfs ################################################################################################################## TK------->>>>>init/do_mounts.c>>>>>>prepare_namespace>>before>mount_root ################################################################################################################## TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_sb->s_type->name is rootfs ################################################################################################################## ################################################################################################################## TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_sb->s_type->name is rootfs ################################################################################################################## yaffs: dev is 32505859 name is 'mtdblock3' yaffs: passed flags '' yaffs: Attempting MTD mount on 31.3, 'mtdblock3' yaffs_read_super: isCheckpointed 0 VFS: Mounted root (yaffs filesystem) on device 31:3. TK------->>>>>init/do_mounts.c>>>>>>prepare_namespace>>before>sys_mount ################################################################################################################## TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_sb->s_type->name is rootfs ################################################################################################################## ################################################################################################################## TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_sb->s_type->name is yaffs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_name.name is root TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_sb->s_type->name is yaffs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_sb->s_type->name is yaffs ################################################################################################################## TK------->>>>>init/do_mounts.c>>>>>>prepare_namespace>>before>sys_chroot ################################################################################################################## TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_sb->s_type->name is rootfs ################################################################################################################## ################################################################################################################## TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_sb->s_type->name is yaffs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_name.name is root TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_sb->s_type->name is yaffs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_sb->s_type->name is yaffs ################################################################################################################## TK------->>>>>fs/open.c>>>>>>SYSCALL_DEFINE1(chroot>>before>set_fs_root ################################################################################################################## TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_sb->s_type->name is rootfs ################################################################################################################## ################################################################################################################## TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_sb->s_type->name is yaffs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_name.name is root TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_sb->s_type->name is yaffs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_sb->s_type->name is yaffs ################################################################################################################## TK------->>>>>init/do_mounts.c>>>>>>SYSCALL_DEFINE1(chroot>>after>set_fs_root ################################################################################################################## TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_sb->s_type->name is yaffs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_name.name is root TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_sb->s_type->name is yaffs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_sb->s_type->name is yaffs ################################################################################################################## ################################################################################################################## TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_sb->s_type->name is yaffs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_name.name is root TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_sb->s_type->name is yaffs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_sb->s_type->name is yaffs ################################################################################################################## TK------->>>>>init/do_mounts.c>>>>>>prepare_namespace>>after>sys_chroot ################################################################################################################## TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_sb->s_type->name is yaffs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_name.name is root TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_sb->s_type->name is yaffs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_sb->s_type->name is yaffs ################################################################################################################## ################################################################################################################## TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_sb->s_type->name is yaffs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_name.name is root TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_sb->s_type->name is yaffs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_sb->s_type->name is yaffs ################################################################################################################## TK------->>>>>init/main.c>>>>>>kernel_init>>after>prepare_namespace ################################################################################################################## TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_sb->s_type->name is yaffs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_name.name is root TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_sb->s_type->name is yaffs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_sb->s_type->name is yaffs ################################################################################################################## ################################################################################################################## TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_sb->s_type->name is yaffs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_name.name is root TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_sb->s_type->name is yaffs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_sb->s_type->name is yaffs ################################################################################################################## Freeing init memory: 156K [16/Apr/2006:14:15:35 +0000] boa: server version Boa/0.94.13 [16/Apr/2006:14:15:35 +0000] boa: server built Mar 26 2009 at 15:28:42. [16/Apr/2006:14:15:35 +0000] boa: starting server pid=681, port 80 Try to bring eth0 interface up......eth0: link down Done Please press Enter to activate this console. [root@FriendlyARM /]# mount rootfs on / type rootfs (rw) /dev/root on / type yaffs (rw,relatime) none on /proc type proc (rw,relatime) none on /sys type sysfs (rw,relatime) none on /proc/bus/usb type usbfs (rw,relatime) none on /dev type ramfs (rw,relatime) none on /dev/pts type devpts (rw,relatime,mode=622) tmpfs on /dev/shm type tmpfs (rw,relatime) none on /tmp type ramfs (rw,relatime) none on /var type ramfs (rw,relatime) [root@FriendlyARM /]# ubuntu下mount出的结果: /dev/sda5 on / type ext3 (rw,errors=remount-ro,commit=0) proc on /proc type proc (rw,noexec,nosuid,nodev) sysfs on /sys type sysfs (rw,noexec,nosuid,nodev) fusectl on /sys/fs/fuse/connections type fusectl (rw) none on /sys/kernel/debug type debugfs (rw) none on /sys/kernel/security type securityfs (rw) udev on /dev type devtmpfs (rw,mode=0755) devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=0620) tmpfs on /run type tmpfs (rw,noexec,nosuid,size=10%,mode=0755) none on /run/lock type tmpfs (rw,noexec,nosuid,nodev,size=5242880) none on /run/shm type tmpfs (rw,nosuid,nodev) /dev/sda7 on /home type ext3 (rw,commit=0) binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,noexec,nosuid,nodev) rpc_pipefs on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw) nfsd on /proc/fs/nfsd type nfsd (rw) gvfs-fuse-daemon on /home/tankai/.gvfs type fuse.gvfs-fuse-daemon (rw,nosuid,nodev,user=tankai) 一个还显示rootfs,一个干脆不显示。这个无关紧要。可能micro2440中执行mount命令还会将系统current根目录的父节点也显示出来;而ubuntu下不会再去关心系统current根目录的父节点。但所有的文件搜索,内核都是从系统current根目录开始向下查找的,因此、可以说我们不能在访问rootfs中除了作为系统current根文件系统之外的其他任何节点。 六、测试用例,说明系统current的文件系统布局,不管在那个目录、其根都不会改变: hello.c #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include 'pnode.h' //#include 'internal.h' #include #include MODULE_LICENSE('Dual BSD/GPL'); static int hello_init(void) { printk(KERN_ALERT 'Hello, world\n'); printk('TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is %s\n',current->fs->root.dentry->d_name.name); printk('TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_sb->s_type->name is %s\n',current->fs->root.dentry->d_sb->s_type->name); printk('TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_name.name is %s\n',current->fs->root.mnt->mnt_mountpoint->d_name.name); printk('TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name is %s\n',current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name); printk('TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_name.name is %s\n',current->fs->root.mnt->mnt_root->d_name.name); printk('TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_sb->s_type->name is %s\n',current->fs->root.mnt->mnt_root->d_sb->s_type->name); printk('TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_sb->s_type->name is %s\n',current->fs->root.mnt->mnt_sb->s_type->name); printk('########################################################################################\n'); printk('TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is %s\n',current->fs->pwd.dentry->d_name.name); printk('TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_sb->s_type->name is %s\n',current->fs->pwd.dentry->d_sb->s_type->name); printk('TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_name.name is %s\n',current->fs->pwd.mnt->mnt_mountpoint->d_name.name); printk('TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name is %s\n',current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name); printk('TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_name.name is %s\n',current->fs->pwd.mnt->mnt_root->d_name.name); printk('TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_sb->s_type->name is %s\n',current->fs->pwd.mnt->mnt_root->d_sb->s_type->name); printk('TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_sb->s_type->name is %s\n',current->fs->pwd.mnt->mnt_sb->s_type->name); return 0; } static void hello_exit(void) { printk(KERN_ALERT'Goodbye, cruel world\n'); } module_init(hello_init); module_exit(hello_exit);Makefile ifneq ($(KERNELRELEASE),) obj-m:=hello.o else KERNELDIR:=/home/android2.3/android2.3_kernel/ PWD:=$(shell pwd) default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules clean: rm -rf *.o *.mod.c *.mod.o *.ko endif make生成hello.ko 先看下文件系统布局: mount rootfs / rootfs ro 0 0 tmpfs /dev tmpfs rw,mode=755 0 0 devpts /dev/pts devpts rw,mode=600 0 0 proc /proc proc rw 0 0 sysfs /sys sysfs rw 0 0 none /acct cgroup rw,cpuacct 0 0 tmpfs /mnt/asec tmpfs rw,mode=755,gid=1000 0 0 tmpfs /mnt/obb tmpfs rw,mode=755,gid=1000 0 0 none /dev/cpuctl cgroup rw,cpu 0 0 /dev/block/mtdblock0 /system yaffs2 rw 0 0 /dev/block/mtdblock1 /data yaffs2 rw,nosuid,nodev 0 0 /dev/block/mtdblock2 /cache yaffs2 rw,nosuid,nodev 0 0 /dev/block/vold/179:0 /mnt/sdcard vfat rw,dirsync,nosuid,nodev,noexec,uid=1000,gid=1015,fmask=0702,dmask=0702,allow_utime=0020,codepage=cp437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 0 /dev/block/vold/179:0 /mnt/secure/asec vfat rw,dirsync,nosuid,nodev,noexec,uid=1000,gid=1015,fmask=0702,dmask=0702,allow_utime=0020,codepage=cp437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 0 tmpfs /mnt/sdcard/.android_secure tmpfs ro,size=0k,mode=000 0 0 1.放入/data/下运行insmod hello.ko rmmod hello.ko Hello, world TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_sb->s_type->name is rootfs ######################################################################################## TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_sb->s_type->name is yaffs2 TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_name.name is data TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_sb->s_type->name is yaffs2 TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_sb->s_type->name is yaffs2 Goodbye, cruel world2.放在/sdcard/tank/下运行insmod hello.ko rmmod hello.koHello, world TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_sb->s_type->name is rootfs ######################################################################################## TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is tank TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_sb->s_type->name is vfat TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_name.name is sdcard TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_name.name is / TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_sb->s_type->name is vfat TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_sb->s_type->name is vfat Goodbye, cruel world 由此证明;current->fs->root就是系统承认的根文件系统。 |
|