文件名为空linux,文件系统:隐匿在Linux背后的机制
原標題:文件系統:隱匿在Linux背后的機制
在 Linux 中,最直觀、最可見的部分就是 文件系統(file system) 。下面我們就來一起探討一下關于 Linux 中國的文件系統,系統調用以及文件系統實現背后的原理和思想。這些思想中有一些來源于 MULTICS,現在已經被 Windows 等其他操作系統使用。Linux 的設計理念就是 小的就是好的(Small is Beautiful) 。雖然 Linux 只是使用了最簡單的機制和少量的系統調用,但是 Linux 卻提供了強大而優雅的文件系統。
Linux 文件系統基本概念
Linux 在最初的設計是 MINIX1 文件系統,它只支持 14 字節的文件名,它的最大文件只支持到 64 MB。在 MINIX 1 之后的文件系統是 ext 文件系統。ext 系統相較于 MINIX 1 來說,在支持字節大小和文件大小上均有很大提升,但是 ext 的速度仍沒有 MINIX 1 快,于是,ext 2 被開發出來,它能夠支持長文件名和大文件,而且具有比 MINIX 1 更好的性能。這使他成為 Linux 的主要文件系統。只不過 Linux 會使用 VFS 曾支持多種文件系統。在 Linux 鏈接時,用戶可以動態的將不同的文件系統掛載倒 VFS 上。
Linux 中的文件是一個任意長度的字節序列,Linux 中的文件可以包含任意信息,比如 ASCII 碼、二進制文件和其他類型的文件是不加區分的。
為了方便起見,文件可以被組織在一個目錄中,目錄存儲成文件的形式在很大程度上可以作為文件處理。目錄可以有子目錄,這樣形成有層次的文件系統,Linux 系統下面的根目錄是 / ,它通常包含了多個子目錄。字符 / 還用于對目錄名進行區分,例如 /usr/cxuan表示的就是根目錄下面的 usr 目錄,其中有一個叫做 cxuan 的子目錄。
下面我們介紹一下 Linux 系統根目錄下面的目錄名
/bin ,它是重要的二進制應用程序,包含二進制文件,系統的所有用戶使用的命令都在這里
/boot ,啟動包含引導加載程序的相關文件
/dev ,包含設備文件,終端文件,USB 或者連接到系統的任何設備
/etc ,配置文件,啟動腳本等,包含所有程序所需要的配置文件,也包含了啟動/停止單個應用程序的啟動和關閉 shell 腳本
/home ,本地主要路徑,所有用戶用 home 目錄存儲個人信息
/lib ,系統庫文件,包含支持位于 /bin 和 /sbin 下的二進制庫文件
/lost+found ,在根目錄下提供一個遺失+查找系統,必須在 root 用戶下才能查看當前目錄下的內容
/media ,掛載可移動介質
/mnt ,掛載文件系統
/opt ,提供一個可選的應用程序安裝目錄
/proc ,特殊的動態目錄,用于維護系統信息和狀態,包括當前運行中進程信息
/root ,root 用戶的主要目錄文件夾
/sbin ,重要的二進制系統文件
/tmp , 系統和用戶創建的臨時文件,系統重啟時,這個目錄下的文件都會被刪除
/usr ,包含絕大多數用戶都能訪問的應用程序和文件
/var ,經常變化的文件,諸如日志文件或數據庫等
在 Linux 中,有兩種路徑,一種是 絕對路徑(absolute path) ,絕對路徑告訴你從根目錄下查找文件,絕對路徑的缺點是太長而且不太方便。還有一種是 相對路徑(relative path) ,相對路徑所在的目錄也叫做 工作目錄(working directory) 。
如果 /usr/local/books 是工作目錄,那么 shell 命令
cp /usr/ local/books/books /usr/ local/books/books-replica
則表示的是絕對路徑。
在 Linux 中經常出現一個用戶使用另一個用戶的文件或者使用文件樹結構中的文件。兩個用戶共享同一個文件,這個文件位于某個用戶的目錄結構中,另一個用戶需要使用這個文件時,必須通過絕對路徑才能引用到他。如果絕對路徑很長,那么每次輸入起來會變的非常麻煩,所以 Linux 提供了一種 鏈接(link) 機制。
舉個例子,下面是一個使用鏈接之前的圖
以上所示,比如有兩個工作賬戶 jianshe 和 cxuan,jianshe 想要使用 cxuan 賬戶下的 A 目錄,那么它可能會輸入 /usr/cxuan/A ,這是一種未使用鏈接之后的圖。
使用鏈接后的示意如下
現在,jianshe 可以創建一個鏈接來使用 cxuan 下面的目錄了。‘
當一個目錄被創建出來后,有兩個目錄項也同時被創建出來,它們就是 . 和 .. ,前者代表工作目錄自身,后者代表該目錄的父目錄,也就是該目錄所在的目錄。這樣一來,在 /usr/jianshe 中訪問 cxuan 中的目錄就是 ../cxuan/xxx
Linux 文件系統不區分磁盤的,這是什么意思呢?一般來說,一個磁盤中的文件系統相互之間保持獨立,如果一個文件系統目錄想要訪問另一個磁盤中的文件系統,在 Windows 中你可以像下面這樣。
兩個文件系統分別在不同的磁盤中,彼此保持獨立。
而在 Linux 中,是支持 掛載 的,它允許一個磁盤掛在到另外一個磁盤上,那么上面的關系會變成下面這樣
掛在之后,兩個文件系統就不再需要關心文件系統在哪個磁盤上了,兩個文件系統彼此可見。
Linux 文件系統的另外一個特性是支持 加鎖(locking) 。在一些應用中會出現兩個或者更多的進程同時使用同一個文件的情況,這樣很可能會導致 競爭條件(race condition) 。一種解決方法是對其進行加不同粒度的鎖,就是為了防止某一個進程只修改某一行記錄從而導致整個文件都不能使用的情況。
POSIX 提供了一種靈活的、不同粒度級別的鎖機制,允許一個進程使用一個不可分割的操作對一個字節或者整個文件進行加鎖。加鎖機制要求嘗試加鎖的進程指定其 要加鎖的文件,開始位置以及要加鎖的字節
Linux 系統提供了兩種鎖: 共享鎖和互斥鎖。如果文件的一部分已經加上了共享鎖,那么再加排他鎖是不會成功的;如果文件系統的一部分已經被加了互斥鎖,那么在互斥鎖解除之前的任何加鎖都不會成功。為了成功加鎖、請求加鎖的部分的所有字節都必須是可用的。
在加鎖階段,進程需要設計好加鎖失敗后的情況,也就是判斷加鎖失敗后是否選擇阻塞,如果選擇阻塞式,那么當已經加鎖的進程中的鎖被刪除時,這個進程會解除阻塞并替換鎖。如果進程選擇非阻塞式的,那么就不會替換這個鎖,會立刻從系統調用中返回,標記狀態碼表示是否加鎖成功,然后進程會選擇下一個時間再次嘗試。
加鎖區域是可以重疊的。下面我們演示了三種不同條件的加鎖區域。
如上圖所示,A 的共享鎖在第四字節到第八字節進行加鎖
如上圖所示,進程在 A 和 B 上同時加了共享鎖,其中 6 - 8 字節是重疊鎖
如上圖所示,進程 A 和 B 和 C 同時加了共享鎖,那么第六字節和第七字節是共享鎖。
如果此時一個進程嘗試在第 6 個字節處加鎖,此時會設置失敗并阻塞,由于該區域被 A B C 同時加鎖,那么只有等到 A B C 都釋放鎖后,進程才能加鎖成功。
Linux 文件系統調用
許多系統調用都會和文件與文件系統有關。我們首先先看一下對單個文件的系統調用,然后再來看一下對整個目錄和文件的系統調用。
為了創建一個新的文件,會使用到 creat 方法,注意沒有 e 。
這里說一個小插曲,曾經有人問 UNIX 創始人 Ken Thompson,如果有機會重新寫 UNIX ,你會怎么辦,他回答自己要把 creat 改成 create ,哈哈哈哈。
這個系統調用的兩個參數是文件名和保護模式
lseek( intfildes, off_toffset, intwhence);
lseek 的返回值是更改文件指針后文件中的絕對位置。lseek 是唯一從來不會造成真正磁盤查找的系統調用,它只是更新當前的文件位置,這個文件位置就是內存中的數字。
對于每個文件,Linux 都會跟蹤文件模式(常規,目錄,特殊文件),大小,最后修改時間以及其他信息。程序能夠通過 stat 系統調用看到這些信息。第一個參數就是文件名,第二個是指向要放置請求信息結構的指針。這些結構的屬性如下圖所示。
fstat 調用和 stat 相同,只有一點區別,fstat 可以對打開文件進行操作,而 stat 只能對路徑進行操作。
pipe 文件系統調用被用來創建 shell 管道。它會創建一系列的 偽文件 ,來緩沖和管道組件之間的數據,并且返回讀取或者寫入緩沖區的文件描述符。在管道中,像是如下操作
sort
sort 進程將會輸出到文件描述符1,也就是標準輸出,寫入管道中,而 head 進程將從管道中讀入。在這種方式中,sort 只是從文件描述符 0 中讀取并寫入到文件描述符 1 (管道)中,甚至不知道它們已經被重定向了。如果沒有重定向的話,sort 會自動的從鍵盤讀入并輸出到屏幕中。
最后一個系統調用是 fcntl ,它用來鎖定和解鎖文件,應用共享鎖和互斥鎖,或者是執行一些文件相關的其他操作。
現在我們來關心一下和整體目錄和文件系統相關的系統調用,而不是把精力放在單個的文件上,下面列出了這些系統調用,我們一起來看一下。
系統調用
描述
s = mkdir(path,mode)
創建一個新的目錄
s = rmdir(path)
移除一個目錄
s = link(oldpath,newpath)
創建指向已有文件的鏈接
s = unlink(path)
取消文件的鏈接
s = chdir(path)
改變工作目錄
dir = opendir(path)
打開一個目錄讀取
s = closedir(dir)
關閉一個目錄
dirent = readdir(dir)
讀取一個目錄項
rewinddir(dir)
回轉目錄使其在此使用
可以使用 mkdir 和 rmdir 創建和刪除目錄。但是需要注意,只有目錄為空時才可以刪除。
創建一個指向已有文件的鏈接時會創建一個 目錄項(directory entry) 。系統調用 link 來創建鏈接,oldpath 代表已有的路徑,newpath 代表需要鏈接的路徑,使用 unlink 可以刪除目錄項。當文件的最后一個鏈接被刪除時,這個文件會被自動刪除。
使用 chdir 系統調用可以改變工作目錄。
最后四個系統調用是用于讀取目錄的。和普通文件類似,他們可以被打開、關閉和讀取。每次調用 readdir 都會以固定的格式返回一個目錄項。用戶不能對目錄執行寫操作,但是可以使用 creat 或者 link 在文件夾中創建一個目錄,或使用 unlink 刪除一個目錄。用戶不能在目錄中查找某個特定文件,但是可以使用 rewindir 作用于一個打開的目錄,使他能在此從頭開始讀取。
責任編輯:
總結
以上是生活随笔為你收集整理的文件名为空linux,文件系统:隐匿在Linux背后的机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: centos7安装php5.2yum源操
- 下一篇: mysql share mode_mys