成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

我們一起學學加載根文件系統

系統 其他OS
可是硬盤中憑什么就有了這些信息呢?這就是個雞生蛋蛋生雞的問題了。你可以先寫一個操作系統,然后給一個硬盤做某種文件系統類型的格式化,這樣你就得到一個有文件系統的硬盤了,有了這個硬盤,你的操作系統就可以成功啟動了。

書接上回,上回書咱們說到,我們已經把硬盤的基本信息存入了 hd_info[]。

把硬盤的分區信息存入了 hd[]。

并且留了個讀取硬盤數據的 bread 函數沒有講,等主流程講完再展開這些函數的細節,我知道這是你們關心的內容。

這些都是 setup 方法里做的事情,也就是進程 0 fork 出的進程 1 所執行的第一個方法。

今天我們說 setup 方法中的最后一個函數 mount_root。

int sys_setup(void * BIOS) {
...
mount_root();
}

mount_root 直譯過來就是加載根。

再多說幾個字是加載根文件系統,有了它之后,操作系統才能從一個根兒開始找到所有存儲在硬盤中的文件,所以它是文件系統的基石,很重要。

我們翻開看看。

void mount_root(void) {
int i,free;
struct super_block * p;
struct m_inode * mi;

for(i=0;i<64;i++)
file_table[i].f_count=0;

for(p = &super_block[0] ; p < &super_block[8] ; p++) {
p->s_dev = 0;
p->s_lock = 0;
p->s_wait = NULL;
}
p=read_super(0);
mi=iget(0,1);

mi->i_count += 3 ;
p->s_isup = p->s_imount = mi;
current->pwd = mi;
current->root = mi;
free=0;
i=p->s_nzones;
while (-- i >= 0)
if (!set_bit(i&8191,p->s_zmap[i>>13]->b_data))
free++;

free=0;
i=p->s_ninodes+1;
while (-- i >= 0)
if (!set_bit(i&8191,p->s_imap[i>>13]->b_data))
free++;
}

很簡單。

從整體上說,它就是要把硬盤中的數據,以文件系統的格式進行解讀,加載到內存中設計好的數據結構,這樣操作系統就可以通過內存中的數據,以文件系統的方式訪問硬盤中的一個個文件了。

那其實搞清楚兩個事情即可:

第一,硬盤中的文件系統格式是怎樣的?

第二,內存中用于文件系統的數據結構有哪些?

我們一個個來。

硬盤中的文件系統格式是怎樣的?

首先硬盤中的文件系統,無非就是硬盤中的一堆數據,我們按照一定格式去解析罷了。Linux-0.11 中的文件系統是 MINIX 文件系統,它就長成這個樣子。

每一個塊結構的大小是 1024 字節,也就是 1KB,硬盤里的數據就按照這個結構,妥善地安排在硬盤里。

可是硬盤中憑什么就有了這些信息呢?這就是個雞生蛋蛋生雞的問題了。你可以先寫一個操作系統,然后給一個硬盤做某種文件系統類型的格式化,這樣你就得到一個有文件系統的硬盤了,有了這個硬盤,你的操作系統就可以成功啟動了。

總之,想個辦法給這個硬盤寫上數據唄。

好了,現在我們簡單看看 MINIX 文件系統的格式。

引導塊就是我們系列最開頭說的啟動區,當然不一定所有的硬盤都有啟動區,但我們還是得預留出這個位置,以保持格式的統一。

超級塊用于描述整個文件系統的整體信息,我們看它的字段就知道了,有后面的 inode 數量,塊數量,第一個塊在哪里等信息。有了它,整個硬盤的布局就清晰了。

inode 位圖和塊位圖,就是位圖的基本操作和作用了,表示后面 inode 和塊的使用情況,和我們之前講的內存占用位圖 mem_map[] 是類似的。

再往后,inode 存放著每個文件或目錄的元信息和索引信息,元信息就是文件類型、文件大小、修改時間等,索引信息就是大小為 9 的 i_zone[9] 塊數組,表示這個文件或目錄的具體數據占用了哪些塊。

其中塊數組里,0~6 表示直接索引,7 表示一次間接索引,8 表示二次間接索引。當文件比較小時,比如只占用 2 個塊就夠了,那就只需要 zone[0] 和 zone[1] 兩個直接索引即可。

再往后,就都是存放具體文件或目錄實際信息的塊了。如果是一個普通文件類型的 inode 指向的塊,那里面就直接是文件的二進制信息。如果是一個目錄類型的 inode 指向的塊,那里面存放的就是這個目錄下的文件和目錄的 inode 索引以及文件或目錄名稱等信息。

好了,文件系統格式的說明,我們就簡單說明完畢了,MINIX 文件系統已經過時。

內存中用于文件系統的數據結構有哪些?

趕緊回過頭來看我們的代碼,是如何加載以這樣一種格式存放在硬盤里的數據,以被我們操作系統所管控的。

從頭看。

struct file {
unsigned short f_mode;
unsigned short f_flags;
unsigned short f_count;
struct m_inode * f_inode;
off_t f_pos;
};

void mount_root(void) {
for(i=0;i<64;i++)
file_table[i].f_count=0;
...
}

把 64 個 file_table 里的 f_count 清零。

這個 file_table 表示進程所使用的文件,進程每使用一個文件,都需要記錄在這里,包括文件類型、文件 inode 索引信息等,而這個 f_count 表示被引用的次數,此時還沒有引用,所以設置為零。

而這個 file_table 的索引,就是我們通常說的文件描述符。比如有如下命令。

echo "hello" > 0

就表示把 hello 輸出到 0 號文件描述符。

0 號文件描述符是哪個文件呢?就是 file_table[0] 所表示的文件。

這個文件在哪里呢?注意到 file 結構里有個 f_inode 字段,通過 f_inode 即可找到它的 inode 信息,inode 信息包含了一個文件所需要的全部信息,包括文件的大小、文件的類型、文件所在的硬盤塊號,這個所在硬盤塊號,就是文件的位置咯。

接著看。

struct super_block super_block[8];
void mount_root(void) {
...
struct super_block * p;
for(p = &super_block[0] ; p < &super_block[8] ; p++) {
p->s_dev = 0;
p->s_lock = 0;
p->s_wait = NULL;
}
...
}

又是把一個數組 super_block 做清零工作。

這個 super_block 存在的意義是,操作系統與一個設備以文件形式進行讀寫訪問時,就需要把這個設備的超級塊信息放在這里。

這樣通過這個超級塊,就可以掌控這個設備的文件系統全局了。

果然,接下來的操作,就是讀取硬盤的超級塊信息到內存中來。

void mount_root(void) {
...
p=read_super(0);
...
}

read_super 就是讀取硬盤中的超級塊。

接下來,讀取根 inode 信息。

struct m_inode * mi;
void mount_root(void) {
...
mi=iget(0,1);
...
}

然后把該 inode 設置為當前進程(也就是進程 1)的當前工作目錄和根目錄。

void mount_root(void) {
...
current->pwd = mi;
current->root = mi;
...
}

然后記錄塊位圖信息。

void mount_root(void) {
...
i=p->s_nzones;
while (-- i >= 0)
set_bit(i&8191, p->s_zmap[i>>13]->b_data);
...
}

最后記錄 inode 位圖信息。

void mount_root(void) {
...
i=p->s_ninodes+1;
while (-- i >= 0)
set_bit(i&8191, p->s_imap[i>>13]->b_data);
}

就完事了。

其實整體上就是把硬盤中文件系統的各個信息,搬到內存中。之前的圖可以說非常直觀了。

有了內存中的這些結構,我們就可以順著根 inode,找到所有的文件了。

至此,加載根文件系統的 mount_root 函數就全部結束了。同時,讓我們回到全局視野,發現 setup 函數也一并結束了。

void main(void) {
...
move_to_user_mode();
if (!fork()) {
init();
}
for(;;) pause();
}

void init(void) {
setup((void *) &drive_info);
...
}

int sys_setup(void * BIOS) {
...
mount_root();
}

setup 的主要工作就是我們今天所講的,加載根文件系統。

我們繼續往下看 init 函數。

void init(void) {
setup((void *) &drive_info);
(void) open("/dev/tty0",O_RDWR,0);
(void) dup(0);
(void) dup(0);
}

看到這相信你也明白了。

之前 setup 函數的一番折騰,加載了根文件系統,順著根 inode 可以找到所有文件,就是為了下一行 open 函數可以通過文件路徑,從硬盤中把一個文件的信息方便地拿到。

在這里,我們 open 了一個 /dev/tty0 的文件,那我們接下來的焦點就在這個 /dev/tty0 是個啥?

責任編輯:武曉燕 來源: 低并發編程
相關推薦

2022-07-28 08:52:08

Docker命令操作系統

2022-12-09 08:34:38

嵌入式Web容器

2024-03-11 10:30:31

Linux文件系統

2021-12-14 09:34:31

丑數順序指針

2022-01-10 06:52:59

拖拽庫項目搜索

2022-09-22 08:06:29

計算機平板微信

2023-11-06 08:28:43

2024-04-29 13:07:00

運維保命原則Oracle

2023-08-02 08:35:54

文件操作數據源

2024-02-28 08:47:29

文件系統數據

2021-09-15 19:02:42

Node.jsFs模塊

2022-03-31 18:59:43

數據庫InnoDBMySQL

2023-08-10 08:28:46

網絡編程通信

2021-08-27 07:06:09

DubboDocker技術

2021-01-12 05:08:49

DHCP協議模型

2022-10-18 07:33:57

Maven構建工具

2023-08-04 08:20:56

DockerfileDocker工具

2023-06-30 08:18:51

敏捷開發模式

2022-05-24 08:21:16

數據安全API

2023-09-10 21:42:31

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美性视频在线播放 | 精品在线视频播放 | www.99精品 | 国产精品日日做人人爱 | 九九久久精品视频 | 日本黄色免费大片 | 国产精品久久久久久久一区二区 | 国产精品中文在线 | 国产精品一区二区三区四区 | 夜夜干夜夜操 | 久久一视频 | 毛片免费观看视频 | 精品久久中文字幕 | 2018国产大陆天天弄 | 日韩欧美大片在线观看 | 国产精品久久久久久久岛一牛影视 | 亚洲精品久久久蜜桃 | 精品视频在线观看 | 日本精品一区二区三区视频 | 免费一级毛片 | 玖玖免费 | 国产精品99免费视频 | 欧美精品一二三区 | 国内精品99 | 中文字幕在线中文 | 一区二区三区在线免费观看视频 | 中文字幕日韩欧美 | 中文字幕在线一区 | 性高湖久久久久久久久aaaaa | 成人av免费| 日韩av资源站 | 97超碰成人| 日韩一级 | 国产激情精品 | 欧美激情一区二区三级高清视频 | 国产午夜精品一区二区三区 | www.日本在线| 国产一区二区久久久 | 在线国产小视频 | 亚洲人人 | 91.com视频|