rootfs

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:

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. #define current (get_current())  
  2. static inline struct task_struct *get_current(void)  

include/linux/sched.h

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. struct task_struct {  
  2.   ......  
  3.   struct thread_info *thread_info;  
  4.   struct list_head tasks;  
  5.   pid_t pid;  
  6.   pid_t tgid;  
  7.   uid_t uid,euid,suid,fsuid;  
  8.   gid_t gid,egid,sgid,fsgid;  
  9.   struct fs_struct *fs;  //本節將大量使用這個  
  10.   struct files_struct *files;  
  11.   ......  
  12. }  

1.文件系統註冊

kernel/include/include/fs.h

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. struct file_system_type {  
  2.   const char *name; //文件系統名字;如:rootfs及ext3等  
  3.   int fs_flags;  
  4.   int (*get_sb) (struct file_system_type *, intconst char *, void *, struct vfsmount *);  
  5.   //安裝/掛載文件系統時,會調用;獲取超級塊。  
  6.   void (*kill_sb) (struct super_block *);  
  7.   //卸載文件系統時會調用。  
  8.   struct module *owner;  
  9.   struct file_system_type * next;  
  10.   //指向下一個文件系統類型。  
  11.   struct list_head fs_supers;  
  12.   //同一個文件系統類型中所有超級塊組成雙向鏈表。  
  13.   struct lock_class_key s_lock_key;  
  14.   struct lock_class_key s_umount_key;  
  15.   
  16.   struct lock_class_key i_lock_key;  
  17.   struct lock_class_key i_mutex_key;  
  18.   struct lock_class_key i_mutex_dir_key;  
  19.   struct lock_class_key i_alloc_sem_key;  
  20. };  

2.文件系統掛載vfsmount(struct vfsmount):

  本質上,mount操作的過程就是新建一個vfsmount結構,然後將此結構和掛載點(目錄項對象)關聯。關聯之後,目錄查找時就能沿着vfsmount掛載點一級級向下查找文件了。
對於每一個mount的文件系統,都由一個vfsmount實例來表示。

kernel/include/linux/mount.h

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. struct vfsmount {  
  2.   struct list_head mnt_hash; //內核通過哈希表對vfsmount進行管理  
  3.   struct vfsmount *mnt_parent;  //指向父文件系統對應的vfsmount  
  4.   struct dentry *mnt_mountpoint; //指向該文件系統掛載點對應的目錄項對象dentry  
  5.   struct dentry *mnt_root; //該文件系統對應的設備根目錄dentry  
  6.   struct super_block *mnt_sb; //指向該文件系統對應的超級塊  
  7.   struct list_head mnt_mounts;   
  8.   struct list_head mnt_child;  //同一個父文件系統中的所有子文件系統通過該字段鏈接成雙聯表  
  9.   int mnt_flags;  
  10.   /* 4 bytes hole on 64bits arches */  
  11.   const char *mnt_devname;  /* Name of device e.g. /dev/dsk/hda1 */  
  12.   struct list_head mnt_list;  //所有已掛載文件系統的vfsmount結構通過該字段鏈接在一起  
  13.   struct list_head mnt_expire;  /* link in fs-specific expiry list */  
  14.   struct list_head mnt_share;   /* circular list of shared mounts */  
  15.   struct list_head mnt_slave_list;/* list of slave mounts */  
  16.   struct list_head mnt_slave;   /* slave list entry */  
  17.   struct vfsmount *mnt_master;  /* slave is on master->mnt_slave_list */  
  18.   struct mnt_namespace *mnt_ns; /* containing namespace */  
  19.   int mnt_id;           /* mount identifier */  
  20.   int mnt_group_id;     /* peer group identifier */  
  21.   /* 
  22.   * We put mnt_count & mnt_expiry_mark at the end of struct vfsmount 
  23.   * to let these frequently modified fields in a separate cache line 
  24.   * (so that reads of mnt_flags wont ping-pong on SMP machines) 
  25.   */  
  26.   atomic_t mnt_count;  
  27.   int mnt_expiry_mark;      /* true if marked for expiry */  
  28.   int mnt_pinned;  
  29.   int mnt_ghosts;  
  30.   /* 
  31.   * This value is not stable unless all of the mnt_writers[] spinlocks 
  32.   * are held, and all mnt_writer[]s on this mount have 0 as their ->count 
  33.   */  
  34.   atomic_t __mnt_writers;  
  35. };  

3.超級塊(struct super_bloc):

kernel/include/linux/fs.h

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. struct super_block {  
  2.   struct list_head  s_list;     /* Keep this first */  
  3.   dev_t         s_dev;      /* search index; _not_ kdev_t */  
  4.   unsigned long     s_blocksize;  
  5.   unsigned char     s_blocksize_bits;  
  6.   unsigned char     s_dirt;  
  7.   unsigned long long    s_maxbytes; /* Max file size */  
  8.   struct file_system_type   *s_type; //文件系統類型  
  9.   //(kernel/include/linux/fs.h,struct file_system_type)  
  10.   const struct super_operations *s_op;  
  11.   struct dquot_operations   *dq_op;  
  12.   struct quotactl_ops   *s_qcop;  
  13.   const struct export_operations *s_export_op;  
  14.   unsigned long     s_flags;  
  15.   unsigned long     s_magic;  
  16.   struct dentry     *s_root;  //超級塊要指向目錄項對象  
  17.   struct rw_semaphore   s_umount;  
  18.   struct mutex      s_lock;  
  19.   int           s_count;  
  20.   int           s_need_sync_fs;  
  21.   atomic_t      s_active;  
  22. #ifdef CONFIG_SECURITY  
  23.   void                    *s_security;  
  24. #endif  
  25.   struct xattr_handler  **s_xattr;  
  26.   
  27.   struct list_head  s_inodes;   /* all inodes */  
  28.   struct list_head  s_dirty;    /* dirty inodes */  
  29.   struct list_head  s_io;       /* parked for writeback */  
  30.   struct list_head  s_more_io;  /* parked for more writeback */  
  31.   struct hlist_head s_anon;//哈希表頭       /* anonymous dentries for (nfs) exporting */  
  32.   struct list_head  s_files;  
  33.   /* s_dentry_lru and s_nr_dentry_unused are protected by dcache_lock */  
  34.   struct list_head  s_dentry_lru;   /* unused dentry lru */  
  35.   int           s_nr_dentry_unused; /* # of dentry on lru */  
  36.   
  37.   struct block_device   *s_bdev;  
  38.   struct mtd_info       *s_mtd;  
  39.   struct list_head  s_instances;  
  40.   struct quota_info s_dquot;    /* Diskquota specific options */  
  41.   
  42.   int           s_frozen;  
  43.   wait_queue_head_t s_wait_unfrozen;  
  44.   
  45.   char s_id[32];                /* Informational name */  
  46.   
  47.   void          *s_fs_info; /* Filesystem private info */  
  48.   fmode_t           s_mode;  
  49.   
  50.   /* 
  51.   * The next field is for VFS *only*. No filesystems have any business 
  52.   * even looking at it. You had been warned. 
  53.   */  
  54.   struct mutex s_vfs_rename_mutex;  /* Kludge */  
  55.   
  56.   /* Granularity of c/m/atime in ns.Cannot be worse than a second */  
  57.   u32          s_time_gran;  
  58.   
  59.   /* 
  60.   * Filesystem subtype.  If non-empty the filesystem type field 
  61.   * in /proc/mounts will be "type.subtype" 
  62.   */  
  63.   char *s_subtype;  
  64.   
  65.   /* 
  66.   * Saved mount options for lazy filesystems using 
  67.   * generic_show_options() 
  68.   */  
  69.   char *s_options;  
  70.   
  71.   /* 
  72.   * storage for asynchronous operations 
  73.   */  
  74.   struct list_head s_async_list;  
  75. };  

4.目錄索引節點(struct inode):

kernel/include/linux/fs.h

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. struct inode {  
  2.   struct hlist_node i_hash; //哈希表節點  
  3.   struct list_head  i_list;  
  4.   struct list_head  i_sb_list;  
  5.   struct list_head  i_dentry;  
  6.   unsigned long     i_ino;  
  7.   atomic_t      i_count;  
  8.   unsigned int      i_nlink;  
  9.   uid_t         i_uid;  
  10.   gid_t         i_gid;  
  11.   dev_t         i_rdev;  
  12.   u64           i_version;  
  13.   loff_t            i_size;  
  14. #ifdef __NEED_I_SIZE_ORDERED  
  15.   seqcount_t        i_size_seqcount;  
  16. #endif  
  17.   struct timespec       i_atime;  
  18.   struct timespec       i_mtime;  
  19.   struct timespec       i_ctime;  
  20.   unsigned int      i_blkbits;  
  21.   blkcnt_t      i_blocks;  
  22.   unsigned short          i_bytes;  
  23.   umode_t           i_mode;  
  24.   spinlock_t        i_lock; /* i_blocks, i_bytes, maybe i_size */  
  25.   struct mutex      i_mutex;  
  26.   struct rw_semaphore   i_alloc_sem;  
  27.   const struct inode_operations *i_op;  
  28.   const struct file_operations  *i_fop; /* former ->i_op->default_file_ops */  
  29.   struct super_block    *i_sb;  
  30.   struct file_lock  *i_flock;  
  31.   struct address_space  *i_mapping;  
  32.   struct address_space  i_data;  
  33. #ifdef CONFIG_QUOTA  
  34.   struct dquot      *i_dquot[MAXQUOTAS];  
  35. #endif  
  36.   struct list_head  i_devices;  
  37.   union {  
  38.     struct pipe_inode_info  *i_pipe;  
  39.     struct block_device *i_bdev;  
  40.     struct cdev     *i_cdev;  
  41.   };  
  42.   int           i_cindex;  
  43.   
  44.   __u32         i_generation;  
  45.   
  46. #ifdef CONFIG_DNOTIFY  
  47.   unsigned long     i_dnotify_mask; /* Directory notify events */  
  48.   struct dnotify_struct *i_dnotify; /* for directory notifications */  
  49. #endif  
  50.   
  51. #ifdef CONFIG_INOTIFY  
  52.   struct list_head  inotify_watches; /* watches on this inode */  
  53.   struct mutex      inotify_mutex;  /* protects the watches list */  
  54. #endif  
  55.   
  56.   unsigned long     i_state;  
  57.   unsigned long     dirtied_when;   /* jiffies of first dirtying */  
  58.   
  59.   unsigned int      i_flags;  
  60.   
  61.   atomic_t      i_writecount;  
  62. #ifdef CONFIG_SECURITY  
  63.   void          *i_security;  
  64. #endif  
  65.   void          *i_private; /* fs or device private pointer */  
  66. };  

5.目錄項對象(struct dentry):

kernel/include/linux/dcache.h

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. struct dentry {  
  2.   atomic_t d_count;  
  3.   unsigned int d_flags;     /* protected by d_lock */  
  4.   spinlock_t d_lock;        /* per dentry lock */  
  5.   int d_mounted;  
  6.   struct inode *d_inode; //目錄項對象與目錄索引的關聯          
  7.   /* Where the name belongs to - NULL is 
  8.   * negative */  
  9.   /* 
  10.   * The next three fields are touched by __d_lookup.  Place them here 
  11.   * so they all fit in a cache line. 
  12.   */  
  13.   struct hlist_node d_hash; //哈希表節點 /* lookup hash list */  
  14.   struct dentry *d_parent; //目錄項對象的父親   /* parent directory */  
  15.   struct qstr d_name; //d_name.name這個是文件名,目錄對象與目錄名的關聯  
  16.   
  17.   struct list_head d_lru;       /* LRU list */  
  18.   /* 
  19.   * d_child and d_rcu can share memory 
  20.   */  
  21.   union {  
  22.     struct list_head d_child;   /* child of parent list */  
  23.     struct rcu_head d_rcu;  
  24.   } d_u;  
  25.   struct list_head d_subdirs;   /* our children */  
  26.   struct list_head d_alias; /* inode alias list */  
  27.   unsigned long d_time;     /* used by d_revalidate */  
  28.   struct dentry_operations *d_op;  
  29.   struct super_block *d_sb; //指向文件系統的超級塊/* The root of the dentry tree */  
  30.   void *d_fsdata;           /* fs-specific data */  
  31.   
  32.   unsigned char d_iname[DNAME_INLINE_LEN_MIN];  /* small names */  
  33. };  

其他:

include/linux/fs.h

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. struct file {  
  2.   /* 
  3.   * fu_list becomes invalid after file_free is called and queued via 
  4.   * fu_rcuhead for RCU freeing 
  5.   */  
  6.   union {  
  7.     struct list_head    fu_list;  
  8.     struct rcu_head     fu_rcuhead;  
  9.   } f_u;  
  10.   struct path       f_path;  //重要!!!記錄掛載信息和目錄項信息  
  11. #define f_dentry    f_path.dentry  
  12. #define f_vfsmnt    f_path.mnt  
  13.   const struct file_operations  *f_op;  
  14.   atomic_long_t     f_count;  
  15.   unsigned int      f_flags;  
  16.   fmode_t           f_mode;  
  17.   loff_t            f_pos;  
  18.   struct fown_struct    f_owner;  
  19.   const struct cred *f_cred;  
  20.   struct file_ra_state  f_ra;  
  21.   
  22.   u64           f_version;  
  23. #ifdef CONFIG_SECURITY  
  24.   void          *f_security;  
  25. #endif  
  26.   /* needed for tty driver, and maybe others */  
  27.   void          *private_data;  
  28.   
  29. #ifdef CONFIG_EPOLL  
  30.   /* Used by fs/eventpoll.c to link all the hooks to this file */  
  31.   struct list_head  f_ep_links;  
  32.   spinlock_t        f_ep_lock;  
  33. #endif /* #ifdef CONFIG_EPOLL */  
  34.   struct address_space  *f_mapping;  
  35. #ifdef CONFIG_DEBUG_WRITECOUNT  
  36.   unsigned long f_mnt_write_state;  
  37. #endif  
  38. };  

include/linux/fs_struct.h

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. struct fs_struct {  
  2.   atomic_t count;  
  3.   rwlock_t lock;  
  4.   int umask;  
  5.   struct path root, pwd; //重要!!!記錄掛載信息和目錄項信息  
  6. };  

include/linux/namei.h

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. struct nameidata {  
  2.   struct path   path;  //重要!!!記錄掛載信息和目錄項信息  
  3.   struct qstr   last;  //重要!!!記錄目錄名  
  4.   unsigned int  flags;  
  5.   int       last_type;  
  6.   unsigned  depth;  
  7.   char *saved_names[MAX_NESTED_LINKS + 1];  
  8.   
  9.   /* Intent data */  
  10.   union {  
  11.     struct open_intent open;  
  12.   } intent;  
  13. };  

include/linux/path.h

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. struct path {  
  2.   struct vfsmount *mnt; //重要!!!記錄文件系統掛載信息  
  3.   struct dentry *dentry;  //重要!!!記錄目錄項信息  
  4. };  

include/linux/dcache.h

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. struct qstr {  
  2.   unsigned int hash;  
  3.   unsigned int len;  
  4.   const unsigned char *name;//重要!!!目錄/文件名字,如"/","tank1"等具體的文件名  
  5. };  

三、註冊/創建、安裝/掛載rootfs,並調用set_fs_root設置系統current的根文件系統爲rootfs

過程:

第一步:建立rootfs文件系統;

第二步:調用其get_sb函數(對於rootfs這種內存/僞文件系統是get_sb_nodev,實際文件系統比如ext2等是get_sb_bdev)、建立超級塊(包含目錄項和i節點);

第三步:掛載該文件系統(該文件系統的掛載點指向該文件系統超級塊的根目錄項);

第四步:將系統current的根文件系統和根目錄設置爲rootfs和其根目錄。

kernel/init/main.c

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. asmlinkage void __init start_kernel(void)  
  2. {  
  3.   setup_arch(&command_line);//解析uboot命令行,實際文件系統掛載需要  
  4.   parse_args("Booting kernel", static_command_line, __start___param,  
  5.            __stop___param - __start___param,  
  6.            &unknown_bootoption);  
  7.   vfs_caches_init(num_physpages);  
  8. }  

kernel/fs/dcache.c

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. void __init vfs_caches_init(unsigned long mempages)  
  2. {  
  3.   mnt_init();  
  4.   bdev_cache_init(); //塊設備文件創建  
  5.   chrdev_init();//字符設備文件創建  
  6. }  

kernel/fs/namespace.c

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. void __init mnt_init(void)  
  2. {  
  3.   init_rootfs(); //向內核註冊rootfs  
  4.   init_mount_tree();//重要!!!rootfs根目錄的建立以及rootfs文件系統的掛載;設置系統current根目錄和根文件系統爲rootfs  
  5. }  

下邊分兩步:

1.向內核註冊rootfs虛擬文件系統init_rootfs

kernel/fs/ramfs/inode.c
[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. int __init init_rootfs(void)  
  2. {  
  3.   err = register_filesystem(&rootfs_fs_type);  
  4. }  
  5. static struct file_system_type rootfs_fs_type = {  
  6.   .name     = "rootfs",  
  7.   .get_sb       = rootfs_get_sb,  
  8.   .kill_sb  = kill_litter_super,  
  9. };  

2.建立rootfs的根目錄,並將rootfs掛載到自己的根目錄;設置系統current根目錄和根文件系統

kernel/fs/namespace.c
[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. static void __init init_mount_tree(void)  
  2. {  
  3.   struct vfsmount *mnt;  
  4.   struct mnt_namespace *ns;  
  5.   struct path root;  
  6.   //創建rootfs的vfsmount結構,建立rootfs的超級塊、並將rootfs掛載到自己的根目錄。  
  7.   /* 
  8.   mnt->mnt_mountpoint = mnt->mnt_root = dget(sb->s_root),而該mnt和自己的sb是關聯的; 
  9.   所以,是把rootfs文件系統掛載到了自己對應的超級塊的根目錄上。 
  10.   這裏也是實現的關鍵:一般文件系統的掛載是調用do_mount->do_new_mount而該函數中首先調用do_kern_mount,這時mnt->mnt_mountpoint = mnt->mnt_root;但後邊 
  11.   它還會調用do_add_mount->graft_tree->attach_recursive_mnt如下代碼mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt)改變了其掛載點!!! 
  12.   */  
  13.   mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);  
  14.   list_add(&mnt->mnt_list, &ns->list);  
  15.   ns->root = mnt; //將創建好的mnt加入系統當前  
  16.   mnt->mnt_ns = ns;  
  17.   
  18.   init_task.nsproxy->mnt_ns = ns; //設置進程的命名空間  
  19.   get_mnt_ns(ns);  
  20.   
  21.   root.mnt = ns->root; //文件系統爲rootfs,相當與root.mnt = mnt;  
  22.   root.dentry = ns->root->mnt_root;//目錄項爲根目錄項,相當與root.dentry = mnt->mnt_root;  
  23.   
  24.   //設置系統current的pwd目錄和文件系統  
  25.   set_fs_pwd(current->fs, &root);  
  26.   //設置系統current根目錄,根文件系統。這個是關鍵!!!整個內核代碼最多隻有兩處調用  
  27.   set_fs_root(current->fs, &root);    
  28. }  

以下着重分析do_kern_mount函數,它實現了rootfs在自己根目錄上的掛載:

kernel/fs/super.c
[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. struct vfsmount *  
  2. do_kern_mount(const char *fstype, int flags, const char *name, void *data)  
  3. {  
  4.   mnt = vfs_kern_mount(type, flags, name, data);  
  5.   return mnt;  
  6. }  

kernel/fs/super.c

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. struct vfsmount *  
  2. vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)  
  3. {  
  4.   mnt = alloc_vfsmnt(name); //建立並填充vfsmount  
  5.   error = type->get_sb(type, flags, name, data, mnt);//爲文件系統建立並填充超級塊(主要是其dentry和inode),建立rootfs根目錄  
  6.   mnt->mnt_mountpoint = mnt->mnt_root; //文件系統掛載點目錄,其實就是剛纔建立的”/”目錄。掛載點就是自己!!!!  
  7.   mnt->mnt_parent = mnt; //父對象是自己!!!!  
  8.   return mnt;  
  9. }  
kernel/fs/ramfs/inode.c
[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. static int rootfs_get_sb(struct file_system_type *fs_type,  
  2.     int flags, const char *dev_name, void *data, struct vfsmount *mnt)  
  3. {  
  4.   return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super,  
  5.                 mnt);  
  6. }  

kernel/fs/super.c

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. int get_sb_nodev(struct file_system_type *fs_type,  
  2.     int flags, void *data,  
  3.     int (*fill_super)(struct super_block *, void *, int),  
  4.     struct vfsmount *mnt)  
  5. {  
  6.   struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);  
  7.   //在內存中分配一個超級塊  
  8.   error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);  
  9.   //執行回調,填充超級塊,並建立根目錄項及對應i節點  
  10.   /* 
  11.   kernel/fs/ramfs/inode.c 
  12.   static int ramfs_fill_super(struct super_block * sb, void * data, int silent) 
  13.   { 
  14.     struct inode * inode; 
  15.     struct dentry * root; 
  16.     sb->s_maxbytes = MAX_LFS_FILESIZE; 
  17.     sb->s_blocksize = PAGE_CACHE_SIZE; 
  18.     sb->s_blocksize_bits = PAGE_CACHE_SHIFT; 
  19.     sb->s_magic = RAMFS_MAGIC; 
  20.     sb->s_op = &ramfs_ops; 
  21.     //static const struct super_operations ramfs_ops; 
  22.     sb->s_time_gran = 1; 
  23.     //建立根目錄索引節點,我們最終的目標是要找到目錄項對象關聯的索引節點。 
  24.     //根目錄索引節點會有自己的ops。 
  25.     inode = ramfs_get_inode(sb, S_IFDIR | 0755, 0);  
  26.     //ramfs_get_inode 
  27.     kernel/fs/ramfs/inode.c 
  28.     struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev) 
  29.     { 
  30.       struct inode * inode = new_inode(sb); 
  31.       switch (mode & S_IFMT) {  //判斷文件類型 
  32.         default: 
  33.       init_special_inode(inode, mode, dev); 
  34.       //init_special_inode 
  35.           void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev) 
  36.           { 
  37.         inode->i_mode = mode; 
  38.         if (S_ISCHR(mode)) {//字符設備文件 
  39.           inode->i_fop = &def_chr_fops; 
  40.           inode->i_rdev = rdev; 
  41.         } else if (S_ISBLK(mode)) {//塊設備文件 
  42.           inode->i_fop = &def_blk_fops; 
  43.           inode->i_rdev = rdev; 
  44.         } else if (S_ISFIFO(mode)) 
  45.           inode->i_fop = &def_fifo_fops; 
  46.         else if (S_ISSOCK(mode)) //網絡設備文件 
  47.           inode->i_fop = &bad_sock_fops; 
  48.         else 
  49.           printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o) for" 
  50.                   " inode %s:%lu\n", mode, inode->i_sb->s_id, 
  51.                   inode->i_ino); 
  52.            } 
  53.           //init_special_inode end 
  54.           break; 
  55.         case S_IFREG: //普通文件 
  56.           inode->i_op = &ramfs_file_inode_operations;  //索引節點的操作方法 
  57.           inode->i_fop = &ramfs_file_operations;  //缺省普通文件的操作方法 
  58.           break; 
  59.         case S_IFDIR:  //目錄文件 
  60.           inode->i_op = &ramfs_dir_inode_operations; 
  61.           //ramfs_dir_inode_operations 
  62.           static const struct inode_operations ramfs_dir_inode_operations; 
  63.           kernel/include/linux/fs.h 
  64.           struct inode_operations { 
  65.             int (*create) (struct inode *,struct dentry *,int, struct nameidata *); 
  66.             int (*mkdir) (struct inode *,struct dentry *,int); 
  67.         int (*rmdir) (struct inode *,struct dentry *); 
  68.         int (*mknod) (struct inode *,struct dentry *,int,dev_t); 
  69.           } 
  70.           //ramfs_dir_inode_operations end 
  71.           inode->i_fop = &simple_dir_operations;  //目錄文件的操作方法 
  72.           inc_nlink(inode); 
  73.           break; 
  74.       } 
  75.     } 
  76.     //ramfs_get_inode end 
  77.     //建立根目錄目錄對象,目錄項對象的存在主要是爲了我們進行路徑的查找。 
  78.     root = d_alloc_root(inode);    
  79.     //d_alloc_root 
  80.     kernel/fs/dcache.c 
  81.     struct dentry * d_alloc_root(struct inode * root_inode) 
  82.     { 
  83.       struct dentry *res = NULL; 
  84.       static const struct qstr name = { .name = "/", .len = 1 }; 
  85.       res = d_alloc(NULL, &name); 
  86.       res->d_sb = root_inode->i_sb; //指向該文件系統的超級塊 
  87.       res->d_parent = res;  //根目錄的父親是它自己 
  88.       d_instantiate(res, root_inode); //關聯 dentry 和 inode 
  89.     } 
  90.     //d_alloc_root end 
  91.     sb->s_root = root;  //超級塊的s_root指向剛建立的根目錄對象。 
  92.   } 
  93.   */  
  94.   return simple_set_mnt(mnt, s); //關聯超級塊(包含目錄項dentry和i節點inode)和vfsmount  
  95. }  
kernel/fs/namespace.c
[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb)  
  2. {  
  3.   printk("TK-------_>>>>>>>namespace.c>>>>simple_set_mnt\n");//add by tankai  
  4.   mnt->mnt_sb = sb;  //對 mnt_sb超級塊指針附值  
  5.   mnt->mnt_root = dget(sb->s_root); //對mnt_root指向的根目錄賦值  
  6.   return 0;  
  7. }  

至此,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
[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. static int __init kernel_init(void * unused){  
  2.   ......  
  3.   do_basic_setup();  //初始化設備驅動,加載靜態內核模塊;釋放Initramfs到rootfs  
  4.   /* 
  5.   kernel/init/initramfs.c 
  6.   rootfs_initcall(populate_rootfs); 
  7.   static int __init populate_rootfs(void) 
  8.   { 
  9.     printk(KERN_INFO "checking if image is initramfs..."); 
  10.     err = unpack_to_rootfs((char *)initrd_start, 
  11.                         initrd_end - initrd_start, 1); //釋放ramdisk到rootfs 
  12.   } 
  13.   */  
  14.   ......  
  15.   if (!ramdisk_execute_command)  ramdisk_execute_command = "/init";  
  16.   if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {  
  17.     ramdisk_execute_command = NULL;  
  18.     //如果此時rootfs中沒有init,則加載initfd、nfs或磁盤文件系統  
  19.     //也即磁盤的文件系統掛載至rootfs的/root目錄,並設置系統current對應的根目錄項爲磁盤根目錄項、系統current根文件系統爲磁盤文件系統  
  20.     //至此,rootfs對於以後所有進程而言、已被隱藏。  
  21.     prepare_namespace();   
  22.   }  
  23.   init_post(); //啓動init進程  
  24.   ......  
  25. }  

看看init_post實現:

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. static noinline int init_post(void)  
  2. {  
  3.   if (ramdisk_execute_command) {  //Initramfs從這裏啓動init  
  4.     run_init_process(ramdisk_execute_command);  
  5.     printk(KERN_WARNING "Failed to execute %s\n", ramdisk_execute_command);  
  6.   }  
  7.   //initrd、nfs和磁盤都是從如下啓動的init  
  8.   if (execute_command) {  
  9.     run_init_process(execute_command);  
  10.     printk(KERN_WARNING "Failed to execute %s.  Attempting "  
  11.                     "defaults...\n", execute_command);  
  12.   }  
  13.   //一般執行如下  
  14.   run_init_process("/sbin/init");  
  15.   run_init_process("/etc/init");  
  16.   run_init_process("/bin/init");  
  17.   run_init_process("/bin/sh");  
  18. }  

四、掛載實際文件系統至rootfs,並調用set_fs_root設置爲系統current的根文件系統

下邊從uboot啓動內核參數的角度來簡單說明:

以下三種情況都是將文件系統掛載到rootfs的/root目錄,並將系統current的根目錄切換爲/root、系統current的根文件系統切換爲磁盤文件系統。

kernel/init/do_mounts.c

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. void __init prepare_namespace(void)  
  2. {  
  3.   if (initrd_load()) //如果掛載initrd並執行成功,則不再掛載磁盤文件系統  
  4.     goto out;  
  5.   if (saved_root_name[0]) {  
  6.     root_device_name = saved_root_name;  
  7.     if (!strncmp(root_device_name, "mtd", 3) ||  
  8.         !strncmp(root_device_name, "ubi", 3)) {  
  9.       mount_block_root(root_device_name, root_mountflags); //啓動時root=參數,如《四.2》中“root=/dev/mtdblock0”  
  10.       goto out;  
  11.     }  
  12.     ROOT_DEV = name_to_dev_t(root_device_name);  
  13.     if (strncmp(root_device_name, "/dev/", 5) == 0)  
  14.       root_device_name += 5;  
  15.   }  
  16.   mount_root(); //將實際文件系統掛載到rootfs的/root目錄  
  17. out:  
  18.   //sys_mount(".", "/", NULL, MS_MOVE, NULL); 這句話無關緊要,影響理解;屏蔽不影響功能  
  19.   sys_chroot(".");  //將當前目錄(/root)設置爲系統current根目錄,磁盤文件系統設置爲系統current根文件系統。  
  20. }  

下邊分兩步解釋mount_root()和sys_chroot(".")調用:

1.將nfs或磁盤文件系統掛載至rootfs的/root目錄(以磁盤爲例)

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. void __init mount_root(void)  
  2. {  
  3.   if (mount_nfs_root())  //如果網絡文件系統掛載成功,則nfs作爲根文件系統  
  4.     return;  
  5.   //掛載磁盤文件系統爲根文件系統  
  6.   //在rootfs中建立/dev/root設備文件  
  7.   create_dev("/dev/root", ROOT_DEV);  //在rootfs中建立/dev/root設備文件,也就是/dev/mtdblock0設備。  
  8.   //掛載/dev/root到rootfs的/root目錄  
  9.   mount_block_root("/dev/root", root_mountflags);  
  10. }  
  11. void __init mount_block_root(char *name, int flags)  
  12. {  
  13.   int err = do_mount_root(name, p, flags, root_mount_data);    
  14. }  
  15. static int __init do_mount_root(char *name, char *fs, int flags, void *data)  
  16. {  
  17.   int err = sys_mount(name, "/root", fs, flags, data);//將/dev/root掛載到/root  
  18.   sys_chdir("/root"); //系統current->fs->pwd爲當前目錄/root  
  19.   ROOT_DEV = current->fs->pwd.mnt->mnt_sb->s_dev;  
  20.   return 0;  
  21. }  

2.將當前目錄/root設置爲系統current根目錄,磁盤文件系統設置爲系統current根文件系統

分析sys_chroot("."):見Linux內核編程之C語言預處理功能與宏

fs/open.c

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. SYSCALL_DEFINE1(chroot, const char __user *, filename)  
  2. {  
  3.   struct path path;  
  4.   error = user_path_dir(filename, &path);  
  5.   //這纔是完成切換的關鍵!!!!整個內核代碼只有兩處調用  
  6.   set_fs_root(current->fs, &path);   
  7. }  

注意,如下情況: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出的結果:

[plain] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. rootfs on / type rootfs (rw)  
  2. /dev/root on / type yaffs (rw,relatime)  
  3. none on /proc type proc (rw,relatime)  
  4. none on /sys type sysfs (rw,relatime)  
  5. none on /proc/bus/usb type usbfs (rw,relatime)  
  6. none on /dev type ramfs (rw,relatime)  
  7. none on /dev/pts type devpts (rw,relatime,mode=622)  
  8. tmpfs on /dev/shm type tmpfs (rw,relatime)  
  9. none on /tmp type ramfs (rw,relatime)  
  10. none on /var type ramfs (rw,relatime)  

從log中體會一下這個過程:

[plain] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. s3c2410-rtc s3c2410-rtc: setting system clock to 2006-04-16 22:15:34 UTC (1145225734)  
  2. TK------->>>>>init/main.c>>>>>>kernel_init>>before>prepare_namespace  
  3. ##################################################################################################################  
  4. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is /  
  5. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_sb->s_type->name is rootfs  
  6. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_name.name is /  
  7. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs  
  8. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_name.name is /  
  9. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_sb->s_type->name is rootfs  
  10. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_sb->s_type->name is rootfs  
  11. ##################################################################################################################  
  12. ##################################################################################################################  
  13. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is /  
  14. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_sb->s_type->name is rootfs  
  15. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_name.name is /  
  16. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs  
  17. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_name.name is /  
  18. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_sb->s_type->name is rootfs  
  19. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_sb->s_type->name is rootfs  
  20. ##################################################################################################################  
  21. TK------->>>>>init/do_mounts.c>>>>>>prepare_namespace>>before>mount_root  
  22. ##################################################################################################################  
  23. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is /  
  24. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_sb->s_type->name is rootfs  
  25. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_name.name is /  
  26. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs  
  27. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_name.name is /  
  28. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_sb->s_type->name is rootfs  
  29. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_sb->s_type->name is rootfs  
  30. ##################################################################################################################  
  31. ##################################################################################################################  
  32. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is /  
  33. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_sb->s_type->name is rootfs  
  34. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_name.name is /  
  35. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs  
  36. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_name.name is /  
  37. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_sb->s_type->name is rootfs  
  38. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_sb->s_type->name is rootfs  
  39. ##################################################################################################################  
  40. yaffs: dev is 32505859 name is "mtdblock3"  
  41. yaffs: passed flags ""  
  42. yaffs: Attempting MTD mount on 31.3, "mtdblock3"  
  43. yaffs_read_super: isCheckpointed 0  
  44. VFS: Mounted root (yaffs filesystem) on device 31:3.  
  45. TK------->>>>>init/do_mounts.c>>>>>>prepare_namespace>>before>sys_mount  
  46. ##################################################################################################################  
  47. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is /  
  48. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_sb->s_type->name is rootfs  
  49. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_name.name is /  
  50. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs  
  51. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_name.name is /  
  52. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_sb->s_type->name is rootfs  
  53. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_sb->s_type->name is rootfs  
  54. ##################################################################################################################  
  55. ##################################################################################################################  
  56. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is /  
  57. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_sb->s_type->name is yaffs  
  58. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_name.name is root  
  59. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs  
  60. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_name.name is /  
  61. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_sb->s_type->name is yaffs  
  62. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_sb->s_type->name is yaffs  
  63. ##################################################################################################################  
  64. TK------->>>>>init/do_mounts.c>>>>>>prepare_namespace>>before>sys_chroot  
  65. ##################################################################################################################  
  66. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is /  
  67. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_sb->s_type->name is rootfs  
  68. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_name.name is /  
  69. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs  
  70. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_name.name is /  
  71. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_sb->s_type->name is rootfs  
  72. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_sb->s_type->name is rootfs  
  73. ##################################################################################################################  
  74. ##################################################################################################################  
  75. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is /  
  76. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_sb->s_type->name is yaffs  
  77. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_name.name is root  
  78. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs  
  79. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_name.name is /  
  80. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_sb->s_type->name is yaffs  
  81. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_sb->s_type->name is yaffs  
  82. ##################################################################################################################  
  83. TK------->>>>>fs/open.c>>>>>>SYSCALL_DEFINE1(chroot>>before>set_fs_root  
  84. ##################################################################################################################  
  85. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is /  
  86. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_sb->s_type->name is rootfs  
  87. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_name.name is /  
  88. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs  
  89. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_name.name is /  
  90. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_sb->s_type->name is rootfs  
  91. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_sb->s_type->name is rootfs  
  92. ##################################################################################################################  
  93. ##################################################################################################################  
  94. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is /  
  95. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_sb->s_type->name is yaffs  
  96. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_name.name is root  
  97. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs  
  98. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_name.name is /  
  99. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_sb->s_type->name is yaffs  
  100. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_sb->s_type->name is yaffs  
  101. ##################################################################################################################  
  102. TK------->>>>>init/do_mounts.c>>>>>>SYSCALL_DEFINE1(chroot>>after>set_fs_root  
  103. ##################################################################################################################  
  104. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is /  
  105. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_sb->s_type->name is yaffs  
  106. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_name.name is root  
  107. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs  
  108. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_name.name is /  
  109. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_sb->s_type->name is yaffs  
  110. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_sb->s_type->name is yaffs  
  111. ##################################################################################################################  
  112. ##################################################################################################################  
  113. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is /  
  114. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_sb->s_type->name is yaffs  
  115. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_name.name is root  
  116. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs  
  117. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_name.name is /  
  118. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_sb->s_type->name is yaffs  
  119. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_sb->s_type->name is yaffs  
  120. ##################################################################################################################  
  121. TK------->>>>>init/do_mounts.c>>>>>>prepare_namespace>>after>sys_chroot  
  122. ##################################################################################################################  
  123. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is /  
  124. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_sb->s_type->name is yaffs  
  125. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_name.name is root  
  126. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs  
  127. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_name.name is /  
  128. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_sb->s_type->name is yaffs  
  129. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_sb->s_type->name is yaffs  
  130. ##################################################################################################################  
  131. ##################################################################################################################  
  132. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is /  
  133. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_sb->s_type->name is yaffs  
  134. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_name.name is root  
  135. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs  
  136. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_name.name is /  
  137. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_sb->s_type->name is yaffs  
  138. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_sb->s_type->name is yaffs  
  139. ##################################################################################################################  
  140. TK------->>>>>init/main.c>>>>>>kernel_init>>after>prepare_namespace  
  141. ##################################################################################################################  
  142. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is /  
  143. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_sb->s_type->name is yaffs  
  144. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_name.name is root  
  145. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs  
  146. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_name.name is /  
  147. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_sb->s_type->name is yaffs  
  148. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_sb->s_type->name is yaffs  
  149. ##################################################################################################################  
  150. ##################################################################################################################  
  151. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is /  
  152. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_sb->s_type->name is yaffs  
  153. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_name.name is root  
  154. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs  
  155. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_name.name is /  
  156. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_sb->s_type->name is yaffs  
  157. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_sb->s_type->name is yaffs  
  158. ##################################################################################################################  
  159. Freeing init memory: 156K  
  160. [16/Apr/2006:14:15:35 +0000] boa: server version Boa/0.94.13  
  161. [16/Apr/2006:14:15:35 +0000] boa: server built Mar 26 2009 at 15:28:42.  
  162. [16/Apr/2006:14:15:35 +0000] boa: starting server pid=681, port 80  
  163.                           
  164. Try to bring eth0 interface up......eth0: link down  
  165. Done  
  166.   
  167. Please press Enter to activate this console.   
  168. [root@FriendlyARM /]# mount  
  169. rootfs on / type rootfs (rw)  
  170. /dev/root on / type yaffs (rw,relatime)  
  171. none on /proc type proc (rw,relatime)  
  172. none on /sys type sysfs (rw,relatime)  
  173. none on /proc/bus/usb type usbfs (rw,relatime)  
  174. none on /dev type ramfs (rw,relatime)  
  175. none on /dev/pts type devpts (rw,relatime,mode=622)  
  176. tmpfs on /dev/shm type tmpfs (rw,relatime)  
  177. none on /tmp type ramfs (rw,relatime)  
  178. none on /var type ramfs (rw,relatime)  
  179. [root@FriendlyARM /]#   

ubuntu下mount出的結果:

[plain] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. /dev/sda5 on / type ext3 (rw,errors=remount-ro,commit=0)  
  2. proc on /proc type proc (rw,noexec,nosuid,nodev)  
  3. sysfs on /sys type sysfs (rw,noexec,nosuid,nodev)  
  4. fusectl on /sys/fs/fuse/connections type fusectl (rw)  
  5. none on /sys/kernel/debug type debugfs (rw)  
  6. none on /sys/kernel/security type securityfs (rw)  
  7. udev on /dev type devtmpfs (rw,mode=0755)  
  8. devpts on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=0620)  
  9. tmpfs on /run type tmpfs (rw,noexec,nosuid,size=10%,mode=0755)  
  10. none on /run/lock type tmpfs (rw,noexec,nosuid,nodev,size=5242880)  
  11. none on /run/shm type tmpfs (rw,nosuid,nodev)  
  12. /dev/sda7 on /home type ext3 (rw,commit=0)  
  13. binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,noexec,nosuid,nodev)  
  14. rpc_pipefs on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw)  
  15. nfsd on /proc/fs/nfsd type nfsd (rw)  
  16. 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

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. #include <linux/syscalls.h>  
  2. #include <linux/slab.h>  
  3. #include <linux/sched.h>  
  4. #include <linux/smp_lock.h>  
  5. #include <linux/init.h>  
  6. #include <linux/kernel.h>  
  7. #include <linux/acct.h>  
  8. #include <linux/capability.h>  
  9. #include <linux/cpumask.h>  
  10. #include <linux/module.h>  
  11. #include <linux/sysfs.h>  
  12. #include <linux/seq_file.h>  
  13. #include <linux/mnt_namespace.h>  
  14. #include <linux/namei.h>  
  15. #include <linux/security.h>  
  16. #include <linux/mount.h>  
  17. #include <linux/ramfs.h>  
  18. #include <linux/log2.h>  
  19. #include <linux/idr.h>  
  20. #include <asm/uaccess.h>  
  21. #include <asm/unistd.h>  
  22. //#include "pnode.h"  
  23. //#include "internal.h"  
  24.   
  25.   
  26. #include <linux/init.h>  
  27. #include <linux/module.h>  
  28. MODULE_LICENSE("Dual BSD/GPL");  
  29.   
  30. static int hello_init(void)  
  31. {  
  32.     printk(KERN_ALERT "Hello, world\n");  
  33.     printk("TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is %s\n",current->fs->root.dentry->d_name.name);  
  34.     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);  
  35.     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);  
  36.     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);  
  37.     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);  
  38.     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);  
  39.     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);  
  40.     printk("########################################################################################\n");  
  41.     printk("TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is %s\n",current->fs->pwd.dentry->d_name.name);  
  42.     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);  
  43.     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);  
  44.     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);  
  45.     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);  
  46.     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);  
  47.     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);  
  48.     return 0;  
  49. }  
  50.   
  51. static void hello_exit(void)  
  52. {  
  53.     printk(KERN_ALERT"Goodbye, cruel world\n");  
  54. }  
  55.   
  56. module_init(hello_init);  
  57. module_exit(hello_exit);  
Makefile
[plain] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. ifneq ($(KERNELRELEASE),)  
  2. obj-m:=hello.o  
  3. else  
  4. KERNELDIR:=/home/android2.3/android2.3_kernel/  
  5. PWD:=$(shell pwd)  
  6. default:  
  7.     $(MAKE) -C $(KERNELDIR)  M=$(PWD) modules  
  8. clean:  
  9.     rm -rf *.o *.mod.c *.mod.o *.ko  
  10. endif  

make生成hello.ko

先看下文件系統佈局:

mount

[plain] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. rootfs / rootfs ro 0 0  
  2. tmpfs /dev tmpfs rw,mode=755 0 0  
  3. devpts /dev/pts devpts rw,mode=600 0 0  
  4. proc /proc proc rw 0 0  
  5. sysfs /sys sysfs rw 0 0  
  6. none /acct cgroup rw,cpuacct 0 0  
  7. tmpfs /mnt/asec tmpfs rw,mode=755,gid=1000 0 0  
  8. tmpfs /mnt/obb tmpfs rw,mode=755,gid=1000 0 0  
  9. none /dev/cpuctl cgroup rw,cpu 0 0  
  10. /dev/block/mtdblock0 /system yaffs2 rw 0 0  
  11. /dev/block/mtdblock1 /data yaffs2 rw,nosuid,nodev 0 0  
  12. /dev/block/mtdblock2 /cache yaffs2 rw,nosuid,nodev 0 0  
  13. /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  
  14. /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  
  15. tmpfs /mnt/sdcard/.android_secure tmpfs ro,size=0k,mode=000 0 0  

1.放入/data/下運行insmod hello.ko rmmod hello.ko

[plain] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. Hello, world  
  2. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is /  
  3. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_sb->s_type->name is rootfs  
  4. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_name.name is /  
  5. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs  
  6. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_name.name is /  
  7. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_sb->s_type->name is rootfs  
  8. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_sb->s_type->name is rootfs  
  9. ########################################################################################  
  10. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is /  
  11. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_sb->s_type->name is yaffs2  
  12. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_name.name is data  
  13. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs  
  14. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_name.name is /  
  15. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_sb->s_type->name is yaffs2  
  16. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_sb->s_type->name is yaffs2  
  17. Goodbye, cruel world  
2.放在/sdcard/tank/下運行insmod hello.ko rmmod hello.ko
[plain] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. Hello, world  
  2. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_name.name is /  
  3. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.dentry->d_sb->s_type->name is rootfs  
  4. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_name.name is /  
  5. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs  
  6. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_name.name is /  
  7. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_root->d_sb->s_type->name is rootfs  
  8. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->root.mnt->mnt_sb->s_type->name is rootfs  
  9. ########################################################################################  
  10. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_name.name is tank  
  11. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.dentry->d_sb->s_type->name is vfat  
  12. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_name.name is sdcard  
  13. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_mountpoint->d_sb->s_type->name is rootfs  
  14. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_name.name is /  
  15. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_root->d_sb->s_type->name is vfat  
  16. TK---->>>>init/main.c>>>kernel_init>>>>current->fs->pwd.mnt->mnt_sb->s_type->name is vfat  
  17. Goodbye, cruel world  

由此證明;current->fs->root就是系統承認的根文件系統。

本文來自:http://blog.csdn.net/tankai19880619/article/details/12093239

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章