rootfs僅僅是符合VFS規範的而且又具有如上3個特點的一個文件系統
說明:本文基於Linux2.6.29內核分析;其他內核版本僅供參考。
Android2.3及Linux2.6.29內核模擬器版本編譯與調試
前邊通過源碼情景分析,看過了總線、設備、驅動及其發現機制,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_head s_list; /* Keep this first */
- dev_t s_dev; /* search index; _not_ kdev_t */
- unsigned long s_blocksize;
- unsigned char s_blocksize_bits;
- unsigned char s_dirt;
- unsigned long long s_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 long s_flags;
- unsigned long s_magic;
- struct dentry *s_root; //超級塊要指向目錄項對象
- struct rw_semaphore s_umount;
- struct mutex s_lock;
- int s_count;
- int s_need_sync_fs;
- atomic_t s_active;
- #ifdef CONFIG_SECURITY
- void *s_security;
- #endif
- struct xattr_handler **s_xattr;
- struct list_head s_inodes; /* all inodes */
- struct list_head s_dirty; /* dirty inodes */
- struct list_head s_io; /* parked for writeback */
- struct list_head s_more_io; /* parked for more writeback */
- struct hlist_head s_anon;//哈希表頭 /* anonymous dentries for (nfs) exporting */
- struct list_head s_files;
- /* s_dentry_lru and s_nr_dentry_unused are protected by dcache_lock */
- struct list_head s_dentry_lru; /* unused dentry lru */
- int s_nr_dentry_unused; /* # of dentry on lru */
- struct block_device *s_bdev;
- struct mtd_info *s_mtd;
- struct list_head s_instances;
- struct quota_info s_dquot; /* Diskquota specific options */
- int s_frozen;
- wait_queue_head_t s_wait_unfrozen;
- char s_id[32]; /* Informational name */
- void *s_fs_info; /* Filesystem private info */
- fmode_t s_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_node i_hash; //哈希表節點
- struct list_head i_list;
- struct list_head i_sb_list;
- struct list_head i_dentry;
- unsigned long i_ino;
- atomic_t i_count;
- unsigned int i_nlink;
- uid_t i_uid;
- gid_t i_gid;
- dev_t i_rdev;
- u64 i_version;
- loff_t i_size;
- #ifdef __NEED_I_SIZE_ORDERED
- seqcount_t i_size_seqcount;
- #endif
- struct timespec i_atime;
- struct timespec i_mtime;
- struct timespec i_ctime;
- unsigned int i_blkbits;
- blkcnt_t i_blocks;
- unsigned short i_bytes;
- umode_t i_mode;
- spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
- struct mutex i_mutex;
- struct rw_semaphore i_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_space i_data;
- #ifdef CONFIG_QUOTA
- struct dquot *i_dquot[MAXQUOTAS];
- #endif
- struct list_head i_devices;
- union {
- struct pipe_inode_info *i_pipe;
- struct block_device *i_bdev;
- struct cdev *i_cdev;
- };
- int i_cindex;
- __u32 i_generation;
- #ifdef CONFIG_DNOTIFY
- unsigned long i_dnotify_mask; /* Directory notify events */
- struct dnotify_struct *i_dnotify; /* for directory notifications */
- #endif
- #ifdef CONFIG_INOTIFY
- struct list_head inotify_watches; /* watches on this inode */
- struct mutex inotify_mutex; /* protects the watches list */
- #endif
- unsigned long i_state;
- unsigned long dirtied_when; /* jiffies of first dirtying */
- unsigned int i_flags;
- atomic_t i_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_head fu_list;
- struct rcu_head fu_rcuhead;
- } f_u;
- struct path f_path; //重要!!!記錄掛載信息和目錄項信息
- #define f_dentry f_path.dentry
- #define f_vfsmnt f_path.mnt
- const struct file_operations *f_op;
- atomic_long_t f_count;
- unsigned int f_flags;
- fmode_t f_mode;
- loff_t f_pos;
- struct fown_struct f_owner;
- const struct cred *f_cred;
- struct file_ra_state f_ra;
- u64 f_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_head f_ep_links;
- spinlock_t f_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 path path; //重要!!!記錄掛載信息和目錄項信息
- struct qstr last; //重要!!!記錄目錄名
- unsigned int flags;
- int last_type;
- unsigned depth;
- 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.c- int __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.c- static 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.c- struct 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;
- }
- static 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
- }
- 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.c- static 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 <linux/syscalls.h>
- #include <linux/slab.h>
- #include <linux/sched.h>
- #include <linux/smp_lock.h>
- #include <linux/init.h>
- #include <linux/kernel.h>
- #include <linux/acct.h>
- #include <linux/capability.h>
- #include <linux/cpumask.h>
- #include <linux/module.h>
- #include <linux/sysfs.h>
- #include <linux/seq_file.h>
- #include <linux/mnt_namespace.h>
- #include <linux/namei.h>
- #include <linux/security.h>
- #include <linux/mount.h>
- #include <linux/ramfs.h>
- #include <linux/log2.h>
- #include <linux/idr.h>
- #include <asm/uaccess.h>
- #include <asm/unistd.h>
- //#include "pnode.h"
- //#include "internal.h"
- #include <linux/init.h>
- #include <linux/module.h>
- 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);
- 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 world
- 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 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就是系統承認的根文件系統。