1. 基礎概念
1.1 系統調用
? ? ? ? 系統調用實際上是Linux內核為上層應用程序提供的API接口,方便應用程序進行調用,類似于SVC。
1.2 庫函數
? ? ? ? 庫函數是應用層里邊的東西,在系統調用的上層,通常以動態庫文件(.so)形式提供。與系統調用區別是:庫函數是屬于應用層,而系統調用是內核提供給應用層的編程接口,屬于系統內核的一部分; 庫函數運行在用戶空間,調用系統調用會由用戶空間(用戶態)陷入到內核空間(內核態); ?庫函數通常是有緩存的,而系統調用是無緩存的,所以在性能、效率上,庫函數通常要優于系統調 用; ?可移植性:庫函數相比于系統調用具有更好的可移植性。
2. I/O基礎
? ? ? ? open/write/read/close等,主要說一下lseek。lseek函數用于設置文件讀寫偏移量,其他詳細信息看手冊。
3. Linux系統下的文件管理
3.1 靜態文件與inode
? ? ? ? 靜態文件:電腦硬盤、移動硬盤、U 盤等外部存儲設 備,文件存放在磁盤文件系統中,并且以一種固定的形式進行存放,我們把他們稱為靜態文件。
? ? ? ? inode:實際上是一個結構體,記錄了文件的不同信息;并且一個inode對應一個文件,多個inode組成一個inode表。可通過命令“ls -i”查看inode號。
3.2?磁盤分區
? ? ? ? 磁盤分為數據區和inode區,數據區用于存儲文件中的數據;inode區用于存放inode表。
? ? ? ? 快速格式化:僅刪除了u盤的inode區,但是沒有刪除數據區,因此可以找回數據。
3.3?文件狀態
? ? ? ? 文件打開過程:首先系統根據文件名找對文件對應的inode編號;然后通過該編號去inode表里邊尋找對應的inode結構體;最后根據結構體里邊記錄的信息,確定文件的數據所在的扇區,最后讀出數據。
? ? ? ? 文件打開狀態:調用open函數去打開文件的時候,內核會申請一段內存(一段緩沖區),并且將靜態文件的數 據內容從磁盤這些存儲設備中讀取到內存中進行管理、緩存(也把內存中的這份文件數據叫做動態文件、內 核緩沖區)。打開文件后,以后對這個文件的讀寫操作,都是針對內存中這一份動態文件進行相關的操作, 而并不是針對磁盤中存放的靜態文件。 當我們對動態文件進行讀寫操作后,此時內存中的動態文件和磁盤設備中的靜態文件就不同步了,數據 的同步工作由內核完成,內核會在之后將內存這份動態文件更新(同步)到磁盤設備中。
? ? ? ? 進程控制塊(PCB):是一個結構體用于記錄進程的狀態信息、運行特征等。
? ? ? ? 文件描述符表、文件表及inode之間的關系:如下圖所示:
PCB中有一個指針指向文件描述符表,該表中的每個元素對應一個文件表;文件表中存在inode指針指向inode用于讀取文件數據。
3.4?perror函數
? ? ? ? 該函數用于查看詳細的報錯信息。比如當調用open函數打開某文件時,如果失敗的話回返回-1,但是并不知道錯誤的詳細原因;因此采用這個函數即可了解,其用法如下所示:
如果失敗,會打印 “open error:加具體原因” 。
3.5?exit、_exit、_Exit函數
? ? ? ? 這三個函數都用于結束進程,類似于return;。調用_exit()函數會 清除其使用的內存空間,并銷毀其在內核中的各種數據結構,關閉進程的所有文件描述符,并結束進程、將 控制權交給操作系統。_exit()和_Exit()兩者等價。
????????exit()函數_exit()函數都是用來終止進程的,exit()是一個標準C庫函數,而_exit()和_Exit()是系統調用。 執行exit()會執行一些清理工作,最后調用_exit()函數。一般用exit()。
用法如下:
3.6?空洞文件
? ? ? ? 比如說現在一個文件a大小是4K;然后我調用了lseek函數將讀寫位置偏印到文件頭部6k個字節處寫數據,那么此時0-4k處有數據,6k處之后有數據,但是4k-6k處沒有數據。該區域就成為文件空洞區域,該文件也被稱為空洞文件。
? ? ? ? 空洞文件邏輯大小和物理大小:ls命令查看到空洞文件的大小是8K,使用ls命令查看到的大小是文件的邏輯大小,自然是包括了 空洞部分大小和真實數據部分大小;當使用du命令查看空洞文件時,其大小顯示為4K,du命令查看到的 大小是文件實際占用存儲塊的大小。
3.7?O_APPEND和O_TRUNC標志
? ? ? ? O_APPEND標志是,調用open函數打開文件, 當每次使用write()函數對文件進行寫操作時,都會自動把文件當前位置偏移量移動到文件末尾,從文件末 尾開始寫入數據,也就是意味著每次寫入數據都是從文件末尾開始。用法為fd=open("./src_file",O_APPEND);
? ? ? ? O_TRUNC標志是:如果使用了這個標志,調用open函數打開文件的時候會將文件 原本的內容全部丟棄,文件大小變為0。
3.8?多次打開同一文件
????????一個進程內多次open打開同一個文件,那么會得到多個不同的文件描述符fd,同理在關閉文件的 時候也需要調用close依次關閉各個文件描述符。
????????一個進程內多次open打開同一個文件,在內存中并不會存在多份動態文件。此處動態文件指的是調用open函數時會將磁盤上的數據讀到一個緩存區,這個區域的文件數據就叫動態文件。
????????同一個文件被多次打開,會得到多個不同的文件描述符,也就意味著會有多個不同的文件表,而文件讀 寫偏移量信息就記錄在文件表數據結構中,所以從這里可以推測不同的文件描述符所對應的讀寫偏移量是 相互獨立的,并沒有關聯在一起,并且文件表中i-node指針指向的都是同一個inode。