溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

基于linux分怎么實(shí)現(xiàn)虛擬文件系統(tǒng)初始化

發(fā)布時間:2021-12-17 09:26:04 來源:億速云 閱讀:135 作者:iii 欄目:大數(shù)據(jù)

本篇內(nèi)容主要講解“基于linux分怎么實(shí)現(xiàn)虛擬文件系統(tǒng)初始化”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“基于linux分怎么實(shí)現(xiàn)虛擬文件系統(tǒng)初始化”吧!

從main函數(shù)開始,直到虛擬文件系統(tǒng)的初始化,路徑是init()->setup()->syssetup();sys_setup主要是注冊了虛擬文件系統(tǒng)下面所有的文件系統(tǒng)。然后掛載根文件系統(tǒng)。下面是初始化代碼。

    

asmlinkage int sys_setup(void)
{
static int callable = 1;

if (!callable)
return -1;
callable = 0;

device_setup();

#ifdef CONFIG_MINIX_FS
register_filesystem(&(struct file_system_type)
{minix_read_super, "minix", 1, NULL});
#endif

#ifdef CONFIG_EXT_FS
register_filesystem(&(struct file_system_type)
{ext_read_super, "ext", 1, NULL});
#endif
......
mount_root();
}              

下面先看一下基本的數(shù)據(jù)結(jié)構(gòu)。

   
     
 
    
    

struct file_system_type {
struct super_block *(*read_super) (struct super_block *, void *, int);
char *name;
int requires_dev;
struct file_system_type * next;
};              

這是一個具體文件系統(tǒng)在虛擬文件系統(tǒng)注冊時的表示結(jié)構(gòu)。然后看一下注冊文件系統(tǒng)的函數(shù)。

   
     
 
    
    

int register_filesystem(struct file_system_type * fs)
{
struct file_system_type ** tmp;

if (!fs)
return -EINVAL;
if (fs->next)
return -EBUSY;
// tmp是二級指針,指向文件系統(tǒng)鏈表的頭指針的地址
tmp = &file_systems;
// 遍歷鏈表,直到尾部,插入新的節(jié)點(diǎn)
while (*tmp) {
// 判斷是否已經(jīng)注冊了該文件系統(tǒng)
if (strcmp((*tmp)->name, fs->name) == 0)
return -EBUSY;
// 指向當(dāng)前節(jié)點(diǎn)的next域的地址,*tmp得到下一個被比較的節(jié)點(diǎn)
tmp = &(*tmp)->next;
}
// 利用二級指針指針修改next域的內(nèi)容,不需要使用->next = fs的形式
*tmp = fs;
return 0;
}              

就是把一個file_system_type結(jié)構(gòu)體插入一個鏈表中。注冊文件系統(tǒng)其實(shí)只是構(gòu)建一個單鏈表。接著看掛載根文件系統(tǒng)。這里大致分析一下流程。有時間再詳細(xì)說。

   
     
 
    
    

void mount_root(void)
{
struct file_system_type * fs_type;
struct super_block * sb;
struct inode * inode, d_inode;
struct file filp;
int retval;
// 清空超級塊數(shù)組
memset(super_blocks, 0, sizeof(super_blocks));
#ifdef CONFIG_BLK_DEV_FD
if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n");
wait_for_keypress();
}
#endif

memset(&filp, 0, sizeof(filp));
memset(&d_inode, 0, sizeof(d_inode));
// 根設(shè)備號
d_inode.i_rdev = ROOT_DEV;
filp.f_inode = &d_inode;
// 只讀方式掛載
if ( root_mountflags & MS_RDONLY)
filp.f_mode = 1; /* read only */
else
filp.f_mode = 3; /* read write */
// 暫時忽略
retval = blkdev_open(&d_inode, &filp);
if(retval == -EROFS){
root_mountflags |= MS_RDONLY;
filp.f_mode = 1;
retval = blkdev_open(&d_inode, &filp);
}

for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) {
if(retval)
break;
// 沒有關(guān)聯(lián)到設(shè)備則不需要往下執(zhí)行,有些文件系統(tǒng)是沒有對應(yīng)的底層設(shè)備的
if (!fs_type->requires_dev)
continue;
// 讀根設(shè)備的超級塊,設(shè)備的第一扇區(qū)是分區(qū)表,接著是超級塊
sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,NULL,1);
// 讀取成功
if (sb) {
// 根節(jié)點(diǎn)
inode = sb->s_mounted;
inode->i_count += 3 ; /* NOTE! it is logically used 4 times, not 1 */
sb->s_covered = inode;
sb->s_flags = root_mountflags;
// 當(dāng)前進(jìn)程(init進(jìn)程)的根目錄和工作目錄設(shè)置為根節(jié)點(diǎn)
current->fs->pwd = inode;
current->fs->root = inode;
printk ("VFS: Mounted root (%s filesystem)%s.\n",
fs_type->name,
(sb->s_flags & MS_RDONLY) ? " readonly" : "");
// 直接返回,即第一個讀取成功的文件系統(tǒng)成為根文件系統(tǒng)
return;
}
}
panic("VFS: Unable to mount root fs on %02x:%02x",
MAJOR(ROOT_DEV), MINOR(ROOT_DEV));
}              

讀取根設(shè)備的超級塊內(nèi)容,如果成功,則成為根文件系統(tǒng)。并設(shè)置當(dāng)前init進(jìn)程的工作目錄和根目錄是根文件系統(tǒng)的根節(jié)點(diǎn)對應(yīng)的inode。我們看看怎么讀取超級塊的。

   
     
 
    
    

// 讀設(shè)備對應(yīng)的超級塊
static struct super_block * read_super(dev_t dev,char *name,int flags,
  void *data, int silent)
{
struct super_block * s;
struct file_system_type *type;

if (!dev)
return NULL;
check_disk_change(dev);
// 有則直接返回,初始化的時候還沒有
s = get_super(dev);
if (s)
return s;
// 否則根據(jù)name在文件系統(tǒng)鏈表中(在系統(tǒng)初始化時建立的)找到對應(yīng)的文件系統(tǒng)節(jié)點(diǎn),里面有一個read_super函數(shù)
if (!(type = get_fs_type(name))) {
printk("VFS: on device %d/%d: get_fs_type(%s) failed\n",
MAJOR(dev), MINOR(dev), name);
return NULL;
}
// 在超級塊數(shù)組中找到一個slot
for (s = 0+super_blocks ;; s++) {
if (s >= NR_SUPER+super_blocks)
return NULL;
if (!s->s_dev)
break;
}
// 賦值給超級塊節(jié)點(diǎn)的字段
s->s_dev = dev;
s->s_flags = flags;
// 調(diào)底層的文件系統(tǒng)到硬盤去讀取超級塊內(nèi)容,比如ext文件系統(tǒng),ext2文件系統(tǒng)等等都定義了該函數(shù)。
if (!type->read_super(s,data, silent)) {
s->s_dev = 0;
return NULL;
}
s->s_dev = dev;
s->s_covered = NULL;
s->s_rd_only = 0;
s->s_dirt = 0;
s->s_type = type;
return s;
}              

主要是獲取一個超級塊結(jié)構(gòu)體,然后調(diào)底層文件系統(tǒng)的read_super。然后設(shè)置超級塊的屬性。這里分析一下ext文件系統(tǒng)的read_super。

   
     
 
    
    

struct super_block *ext_read_super(struct super_block *s,void *data,
  int silent)
{
struct buffer_head *bh;
struct ext_super_block *es;
int dev = s->s_dev,block;

lock_super(s);
set_blocksize(dev, BLOCK_SIZE);
// 讀取設(shè)備的內(nèi)容,即超級塊的內(nèi)容
if (!(bh = bread(dev, 1, BLOCK_SIZE))) {
s->s_dev=0;
unlock_super(s);
printk("EXT-fs: unable to read superblock\n");
return NULL;
}
// 文件系統(tǒng)的一些屬性
es = (struct ext_super_block *) bh->b_data;
s->s_blocksize = 1024;
s->s_blocksize_bits = 10;
s->u.ext_sb.s_ninodes = es->s_ninodes;
s->u.ext_sb.s_nzones = es->s_nzones;
s->u.ext_sb.s_firstdatazone = es->s_firstdatazone;
s->u.ext_sb.s_log_zone_size = es->s_log_zone_size;
s->u.ext_sb.s_max_size = es->s_max_size;
s->s_magic = es->s_magic;
s->u.ext_sb.s_firstfreeblocknumber = es->s_firstfreeblock;
s->u.ext_sb.s_freeblockscount = es->s_freeblockscount;
s->u.ext_sb.s_firstfreeinodenumber = es->s_firstfreeinode;
s->u.ext_sb.s_freeinodescount = es->s_freeinodescount;
brelse(bh);
if (s->s_magic != EXT_SUPER_MAGIC) {
s->s_dev = 0;
unlock_super(s);
if (!silent)
printk("VFS: Can't find an extfs filesystem on dev 0x%04x.\n",
  dev);
return NULL;
}
if (!s->u.ext_sb.s_firstfreeblocknumber)
s->u.ext_sb.s_firstfreeblock = NULL;
else
if (!(s->u.ext_sb.s_firstfreeblock = bread(dev,
s->u.ext_sb.s_firstfreeblocknumber, BLOCK_SIZE))) {
printk("ext_read_super: unable to read first free block\n");
s->s_dev = 0;
unlock_super(s);
return NULL;
}
if (!s->u.ext_sb.s_firstfreeinodenumber)
s->u.ext_sb.s_firstfreeinodeblock = NULL;
else {
block = 2 + (s->u.ext_sb.s_firstfreeinodenumber - 1) / EXT_INODES_PER_BLOCK;
if (!(s->u.ext_sb.s_firstfreeinodeblock = bread(dev, block, BLOCK_SIZE))) {
printk("ext_read_super: unable to read first free inode block\n");
brelse(s->u.ext_sb.s_firstfreeblock);
s->s_dev = 0;
unlock_super (s);
return NULL;
}
}
unlock_super(s);
/* set up enough so that it can read an inode */
s->s_dev = dev;
// 操作函數(shù)集
s->s_op = &ext_sops;
// 讀取根節(jié)點(diǎn)
if (!(s->s_mounted = iget(s,EXT_ROOT_INO))) {
s->s_dev=0;
printk("EXT-fs: get root inode failed\n");
return NULL;
}
return s;
}              

主要工作是讀取硬盤的超級塊信息到內(nèi)存,最后讀取根節(jié)點(diǎn)對應(yīng)的inode。

到此,相信大家對“基于linux分怎么實(shí)現(xiàn)虛擬文件系統(tǒng)初始化”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI