天天看點

201913217、8章讀書筆記

第7章 檔案操作

(1) 硬體級别

fdisk:将硬碟、u盤h或SDC槽分區

mkfs:格式化磁盤分區,為系統做好準備

fsck:檢查和維修系統

碎片整理:壓縮檔案系統中的檔案

(2)作業系統核心中的檔案系統函數

201913217、8章讀書筆記

(3)系統調用

使用者模式程式使用系統調用來通路核心函數。就是調用上述函數

(4)I/O庫函數

使用者通常需要讀/寫單獨的字元、行或資料結構記錄等,系統調用的是資料塊,無意義

(5)使用者指令

使用者指令:使用者可以使用Unix/Linux指令來執行檔案操作,而不是編寫程式。

(6) sh腳本

比系統調用友善得多,但是必須要手動輸入指令,如果使用的是GUI, 必須要拖放檔案圖示和點選指向裝置來輸入,操作煩瑣而且耗時。

201913217、8章讀書筆記

(1 )使用者模式下的程式執行操作

FILE *fp = fopen("file", "r") ; or FILE fp = fopen(''file^, ”w");

可以打開一個讀/寫檔案流。

(2) fopen()在使用者(heap)空間中建立一個FILE結構體,包含一個檔案描述符fd、一 個fbuf [BLKSIZE]和一些控制變最。它會向核心中的kopen()發出一個fd = open("file", flags=READ or WRITE)系統調用,建構一個。penTable來表示打開檔案示例。OpenTable 的mptr指向記憶體中的檔案INODEo對于非特殊檔案,INODE的i_block數組指向存儲設 備上的資料塊。成功後. fp會指向FILE結構體,其中fd是open。系統調用傳回的檔案描 述符。

(3 ) freadfubuf, size, nitem, fp):将 nitem 個 size 位元組讀取到 ubuf 上,通過:

•将資料從FILE結構體的ftuf±複制到ubuf上,若資料足夠,則傳回。

・如果fbuf沒有更多資料,則執行(4a)。

( 4a)發岀read(fd, fbuf, BLKSIZE)系統調用,将檔案資料塊從核心讀取到fbuf上,然 後将資料複制到ubuf上,直到資料足夠或者檔案無更多資料可複制。

(4b) fwrite(ubuf, size, nitem, fp):将資料從 ubuf 複制到 fbufe

•若(fbuf有空間):将資料複制到fbuf上,并傳回。

•若(fbuf已滿):發出write(fd, ftuf, BLKSIZE)系統調用,将資料塊寫入核心,然後 再次寫入fbuf。

這樣,fread()/fwrite()會向核心發岀read()/write。系統調用,但僅在必要時發出,而且 它們會以塊集大小來傳輸資料,提高效率。同樣,其他庫I/O函數.如fgetc/fputc、fgets/ Iputs, fscanf/fprintf等也可以在使用者空間内的FILE結構體中對命uf進行操作“

(5)核心中的檔案系統函數:

假設非特殊檔案的read(fd, fbuf[ ], BLKSIZE)系統調用”

(6)在read。系統調用中,fd是一個打開的檔案描述符,它是運作程序的fd數組中的 一個索引,指向一個表示打開檔案的OpenTable0

(7)OpenTable包含檔案的打開模式、一個指向記憶體中檔案INODE的指針和讀/寫文 件的目前位元組偏移量。從0penTable的偏移量,

•計算邏輯塊編号lbk0

•通過INODE.i_block[]數組将邏輯塊編号轉換為實體塊編号blk0

(8 ) Minode包含檔案的記憶體INODE。EMODE.i_block[]數組包含指向實體磁盤塊的指 針。檔案系統可使用實體塊編号從磁盤塊直接讀取資料或将資料直接寫入磁盤塊,但将會導 緻過多的實體磁盤I/O。

(9)為提高磁盤I/O效率,作業系統核心通常會使用一組1/0緩沖區作為高速緩存,以 減少實體I/O的數量。磁盤I/O緩沖區管理将在第12章中讨論。

(9a)對于read(fd, buf, BLKSIZE)系統調用,要确定所需的(dev, blk)編号,然後查詢 I/O緩沖區高速緩存,以執行以下操作:

•get a buffer = (dev, blk);

.if (buffers data are invalid)(

start_io on buffer;

wait for I/O completion;

}

.copy data from buffer to fbuf;

.release buffer to buffer cache;

(9b)對于write(fd, fbuf, BLKSIZE)系統調用,要确定需要的(dev, blk)編号,然後査 詢I/O緩沖區高速緩存,以執行以下操作:

.get a buffer = (dev, blk);

.write data to the I/O buffer;

,mark buffer as dataValid and DIRTY (for delay-write to disk);

.release the buffer to buffer cache;

(10)裝置I/O : I/O緩沖區上的實體I/O最終會仔細檢査裝置驅動程式,裝置驅動程式

由上半部分的start_io()和下半部分的磁盤中斷處理程式組成°

Upper-half of disk driver start_io(bp): Z/bp=a locked buffer in dev_list, opcode=R|W(ASYNC) (

enter bp into devzs I/O_queue;

if (bp is FIRST in I/O_queue) issue I/O command to device;

)

Lower-half o£ disk driver

Device_Interrupt_Handl«r:

(

bp = dequeue(first buffer from dev.I/O_queue);

if (bp was READ)(

mark bp data VALID; wakeup/unblock waiting process on bp;

else // bp was for delay write release bp into buffer cache;

if (dev.I/O_queue NOT empty)

issue I/O command for first buf£er in dev.I/0_queue;

定義:一個塊儲存設備,如硬碟、u盤、SD卡等,可以分為幾個邏輯單元,稱為分區

各分區均可以格式化為特定的檔案系統,也可以安裝在不同的作業系統上。

分區表位于第一個扇 區的位元組偏移446 (OxlBE)處,該扇區稱為裝置的主引導記錄(MB

R)。表有4個條目,每個條目由一個16位元組的分區結構體定義,即:

201913217、8章讀書筆記

fdisk mydisk 在磁盤映像檔案上運作fdisk

fdisk是一個互動程式。它有一個顯示所有指令的幫助菜單。它收集使用者的輸入,在記憶體中 創

建一個分區表,該分區表僅在使用者輸入w指令時才被寫入磁盤映像的MBR。

在記憶體 中,它允許使用者建立、檢査和修改分區。将分區寫入磁盤後,通過q指令退出fdisk

通過t指令将它們更改為不同的檔案系統類型。

fdisk隻是将一個儲存設備劃分為多個分區。每個分區都有特定的檔案系統類型.但是 分區還不

能使用。為了存儲檔案,必須先為特定的檔案系統準備好分區

Linux支援多 種不同類型的檔案系統,每個檔案系統都期望儲存設備上有特定的格式。在Linu

x中,指令

在一個nblocks裝置上建立一個TYPE檔案系統,每表塊都是bsize位元組,如果bsize未指定就默

認為1KB

格式化後的磁盤應是隻包含根目 錄的空檔案系統。但是,Linux的mkfs始終會在根目錄下建立

一個預設的lost+found目錄 完成mkfs之後,裝置就可以使用了。

由于虛拟檔案系統不是真正的裝置,它們必須作為循環裝置挂載

man 8 losetup:顯示用于系統管理的losetup實用工具指令:

(1 )用dd指令建立一個虛拟磁盤映像:

(2 )在vdisk上運作fdisk來建立一個分區Pl:

(3)使用以下扇區數在vdisk的分區1上建立一個循環裝置:

losetup需要分區的開始位元組(start_sector512)和結束位元組(end_sector512 )。循 環裝置建立完成後,讀程序可以使用指令

EXT2檔案系統有1440個塊,每個塊大小為1KB。我們之是以選擇1440塊, 是因為它是(舊)軟碟的塊數,得到的磁盤映像可以直接作為虛拟(軟)磁盤’在模拟基于 Intel x86的大多數PC虛拟機上使用

201913217、8章讀書筆記

Block#0:引導塊B0是引導塊,檔案系統不會使用它。它用于容納從磁盤引導操作系 統的引導程式。

Block#1 :超級塊(在硬碟分區中位元組偏移量為1024 ) B1是超級塊,用于容納關于整 個檔案系統的資訊。

201913217、8章讀書筆記

s_first_data_block : 0表示4KB塊大小,1表示1KB塊大小。它用于确定塊組描述符的 起始塊,即 s_first_data_block + lo

s_log_block_size 确定檔案塊大小,為 lKB*(2**s_log_block_size),例如 0 表示 1KB 塊 大小,1表示2KB塊大小,2表示4KB塊大小,等等。最常用的塊大小是用于小檔案系統 的1KB和用于大檔案系統的4KBO

s_mnt_count :已挂載檔案系統的次數。當挂載計數達到max_mount_count時,fsck會 話将被迫檢查檔案系統的一緻性。

s_magic是辨別檔案系統類型的幻數。EXT2/3/4檔案系統的幻數是0xEF53。

Block#2 :塊組描述符塊(硬碟上的s_first_data_blocks-l ) EXT2将磁盤塊分成幾個 組。每個組有8192個塊(硬碟上的大小為32K)。每組用一個塊組描述符結構體描述。

Block#8 :塊位圖(Bmap) (bg_block_bitmap)位圖是用來表示某種項的位序列,例如 磁盤塊或索引節點。位圖用于配置設定和回收項。在位圖中,0位表示對應項處于FREE狀态, 1位表示對應項處于IN_USE狀态。一個軟碟有1440個塊,但是Block#。未被檔案系統使 用'是以,位圖隻有1439個有效位。無效位視作IN.USE處理,設定為1。

Block#9 :索引節點位圖(Imap) ( bg_inode_bilmap) 一個索引節點就是用來代表一個 檔案的資料結構。EXT2檔案系統是使用有限數量的索引節點建立的。各索引節點的狀态用 B9中Imap中的一個位表示。在EXT2 FS中,前10個索引節點是預留的。是以,空EXT2 FS的Imap以10個1開頭,然後是0。無效位再次設定為1。

Block#10 :索引(開始)節點塊(bg_inode_table)每個檔案都用一個128位元組(EXT4 中的是256位元組)的獨特索引節點結構體表示。

201913217、8章讀書筆記

i_block[15]數組包含指向檔案磁盤塊的指針,這些磁盤塊有:

直接塊:i_block[0]至i-block[ll],指向直接磁盤塊。

間接塊:i-block[12]指向一個包含256個塊編号(對于1 KB BLKSIZE)的磁盤塊, 每個

塊編号指向一個磁盤塊。

雙重間接塊:i_block[13]指向一個指向256個塊的塊,每個塊指向256個磁盤塊。

三重間接塊:i_block[14]是三重間接塊。對于“小型” EXT2檔案系統,我們可以忽 略它。

dir_entry是一種可擴充結構。名稱字段包含1到255個字元,不含終止NULL位元組。是以 dir_entry的rec_len也各不相同。

基本方法是将超級塊(Block#】

或1KB的1024偏移量位置)讀入char buff 1024]中。讓ext2_super_block *p結構體指向buf[]o 然後,利用p->field通路超級塊結構體的各個字段。該方法類似于通路MBR中的分區表

程式以十六進制數字形式列印每個位元組的索引節點位圖。在imap中,位是從低位位址到高位位址線性存儲的。前16位(從低到高)是b' 11111111 11100000',但是被以十六進制形式列印成ff07,這并不能說明什麼資訊,因為位是按相反 順序列印的,即從高位位址到低位位址。

第8章 使用系統調用進行檔案操作

在作業系統中,程序有兩種模式:

核心 (Kmode)

使用者 (Umode)

系統調用(簡稱syscall)是一種允許程序進入Kmode以 執行Umode不允許操作的機制

複刻子程序、修改執行映像.甚至是終止等操作都必須在核心中執行。

系統調用(簡稱syscall)是一種允許程序進入Kmode以 執行Umode不允許操作的機制。

線上手冊頁儲存在/usr/man/目錄中(Goldt等 1995 ;

Kcrrisk 2010, 2017 )o 而在 Ubuntu Linux 中,則儲存在 /usr/share/man 目錄中。

man2 子目錄中列出了所有系統調用手冊頁。

系統調用必須由程式發出,它們的用法就像普通函數調用一樣,每個系統調用都是一個庫函數,它彙集系統調用參數,并最終向作業系統核心發出一個系統調用

硬連結檔案會共享檔案系統中相同的檔案表示資料結構(索引節點)。

檔案連結數會記錄鍊 接到同一索引節點的硬連結數量。

硬連結僅适用于非目錄檔案。否則,它可能會在檔案系統 名稱空間中建立循環,這是不允

許的。

軟連結在以下情況下非常有用:

通過一個較短的名稱來通路一個經常使用的較長路徑名稱

将标準動态庫名稱連結到實際版本的動态庫

軟連結的一個缺點是目标檔案可能不複存在了。

stat/lstat/fstat系統調用可将一個檔案的資訊傳回

注意:

這些函數會傳回指定檔案的資訊。不需要擁有檔案的通路權限即可擷取該資訊,但是需 要指向檔案的路徑中所有指定目

錄的捜索權限。

stat按檔案名統計指向檔案,并在緩沖區中填寫stat資訊。

Istat與stat相同,除非是符号連結,統計連結本身,而不是連結所引用檔案。是以, stat和Istat的差別是:stat遵循連結,

但Istat不是。

fstat與stat相同,也隻在檔案名處說明filedes (由open ( 2 )傳回)所指向的打開檔案。

函數目錄也是一個檔案。我們應該能像其他任何普通檔案一樣,打開一個READ目錄,然 後讀取和顯示它的内容。

因 此,使用者可能無法正确讀取和解釋目錄的内容。鑒于此,POSIX為目錄檔案指定了以下接口函數。

Linux中的dirent結構體是:

要想讀取符号連結檔案的内容,我們必須使用readlink系統調用