首頁  >  文章  >  運維  >  Linux下的檔案類型介紹

Linux下的檔案類型介紹

青灯夜游
青灯夜游轉載
2019-02-26 16:16:263804瀏覽

這篇文章帶給大家的內容是介紹Linux下幾種文件類型,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。 【影片教學推薦:Linux教學

在Linux系統下,有七類檔案類型:

  • 普通檔案(- )

  • 目錄(d)

  • #軟體連結(字元連結L)

  • #套接字檔案(S)

  • 字元裝置(S)

  • ##區塊設備(B)

  • 管道檔案(命名管道P)

普通檔案、目錄、軟連結無需多解釋。以下帶大家了解一下管道檔案、套接字檔案、字元設備、區塊設備類型。

管道檔案

管道分為匿名管道和命名管道。管道都是一端寫入、另一端讀取,它們是單方向資料傳輸的,它們的資料都是直接在記憶體中傳輸的,管道是進程間通訊的一種方式,例如父進程寫,子進程讀。

在shell中匿名管道就是一個管道符號"|",例如ls | grep xxx#,其中ls對應的進程是這個獨立進程組中的父進程,grep對應的進程是子進程,父進程寫子進程讀。

在程式語言中,匿名管道是透過建立兩個檔案句柄或檔案描述子(例如A、B)來實現的,一個檔案句柄用於寫資料(例如A寫入端,資料寫入A將自動推入B中),另一個檔案句柄用於讀取資料(即B)。

對於命名管道,即有名稱的管道,命名管道將檔案保留在檔案系統中,它也稱為FIFO,也就是first in first out。雖然命名管道檔案保留在檔案系統中,但是這個檔案只是使用命名管道的一個入口,在使用命名管道傳輸資料的時候,仍然是在記憶體中進行的,也就是說並不會因為保留在檔案系統上命名管道的效率就低了。

在shell中,可以使用mknod指令或mkfifo指令建立命名管道,在寫某些特殊需求的shell腳本時,命名管道非常有用。實際上,在Bash 4之後就支援協程(使用coproc指令)的功能了(ksh和zsh老早就支援協程),但是協程的需求都能透過命名管道來實現。

一般的管道都是單向通訊的,無法實現雙向通訊的功能,也就是只能一邊寫一邊讀,不能兩邊都能讀、寫。如果要實現雙向通信,可以創建兩根管道(這樣就有4個文件句柄,兩個讀端,兩個寫端),或者使用更方便的套接字。

套接字(Socket)

套接字用來實現兩端通信,正如上面分析的,可以實現雙向管道的進程間通信功能。不僅如此,套接字還能透過網路實現跨主機的進程間通訊功能。

套接字需要成對才有意義,也就是分為兩端,每一端都有用於讀取、寫入的檔案描述符(或檔案句柄),相當於兩根雙向通訊的管道。

套接字依協定族的方式分為兩大類:網路套接字(AF_INET型,依ipv4和ipv6分為inet4和inet6)和Unix Domain套接字(AF_UNIX類型)。當然,從協議族往下,套接字可細分為很多種類型,例如INET套接字可以分為TCP套接字、UDP套接字、鏈結層套接字、Raw套接字等等。其中網路套接字是網路程式設計的基礎與核心。

Unix Domain套接字

對於單機的進程間通信,使用Unix Domain套接字比Inet套接字更好,因為Unix Domain套接字沒有網路通訊元件,也就是少了很多網路功能,它更加輕量級。實際上,某些語言在某些作業系統平台上實現的管道功能就是透過Unix Domain來實現的,可想而知其高效率。

Unix Domain套接字有兩個檔案句柄(例如A、B),這兩個檔案句柄都是同時可讀、可寫的句柄。進程1向A寫入數據,將自動推送到B上,進程2可從B上讀取從A寫入的數據,同理進程2向B寫入數據將自動推送到A上,進程1可從A上讀取從B寫入的資料。如下:

进程1            进程2
------------------------
A   ----------->  B
B   ----------->  A

在程式語言中,建立Unix Domain Socket自然有對應的函數輕鬆建立(可man socketpair)。對於bash shell,可以透過nc命令(NetCat)來創建,或者乾脆使用兩個命名管道來實現對應的功能。如有需要,可自行了解如何在bash shell中使用Unix Domain套接字。

網路套接字

對於跨網路的進程間通信,需要使用網路套接字。每個網路套接字都由5個部分組成,它們稱為套接字的5元組。格式如下:

{protocol, src_addr, src_port, dest_addr, dest_port}

即協定、來源位址、來源連接埠、目標位址、目標連接埠。

每端套接字在核心空間都有兩個buffer(即一對socket有4個buffer),每一端都有recv buffer和send buffer。進程1向自己的套接字的send buffer寫入數據,將發送到對端的recv buffer中,然後對端的進程2就可以從recv buffer中讀取數據,反之亦然。

但是在真正可以讀、寫網路套接字之前,網路套接字還需要一些設定。服務端套接字創建(socket()函數,創建後就會有一個文件句柄或文件描述符供讀、寫操作)後,還要綁定地址(通過bind()函數)和監聽端口(透過listen ()函數),客戶端則只需要建立套接字後,直接使用connect()函數向服務端套接字發起連線請求即可。

對於TCP套接字,客戶端發起連線請求即表示要和服務端進行三次握手(核心完成,和用戶空間進程無關)。將這三次握手的每一次進行細分,第一次客戶端發送SYN請求,服務端接收到SYN後,內核將這個連接放進syn queue中並設置狀態為syn-recv,然後發送ack syn給客戶端,當接收到客戶端回覆ack後,核心將連線從syn queue移到established queue(或accept queue)中並將連線的狀態標記為established。最後等待用戶空間的程序發起accept()系統呼叫讓核心將其從accept queue中移除。被accept()後的連接表示已經建立好的連接,可以真正實現兩端進程間的資料傳輸。

更多關於TCP套接字的原理,請參閱我的另一篇文章:不可不知的socket和TCP連接過程。

區塊設備和字元設備

區塊設備是硬體設備,透過隨機(不一定是順序)存取固定大小的資料區塊(chunk)來區分。固定大小的chunk稱為區塊(block)。 最常見的區塊設備是硬碟,但也存在許多其他區塊設備,如軟碟機、藍光讀取器和快閃記憶體。注意,這些都是掛載檔案系統的設備,檔案系統就像是區塊設備的通用語言。

字元設備透過連續的流資料訪問,一個位元組接著一個位元組。 典型的字元設備是終端機(終端機分多種,由實體的也有虛擬的)和鍵盤

區分區塊裝置和字元裝置最簡單的方法是看資料存取的方式。能隨機存取取得資料的是區塊設備,必須按位元組順序存取的是字元設備

如果可以這裡讀一點數據,那裡讀一點數據,最後串成一整段連續的數據,那麼這個就是塊設備,就像硬碟上的數據是不連續的,有可能需要透過隨機訪問的方式取得一段資料。例如磁碟上一個稍大一點的文件,可能前10k資料是連續的資料塊或在連續的磁區內,之後的10k資料在離它很遠甚至在不同的柱面上。

如果一段資料中的每個位元組都跟存取時的位元組順序是一樣的,即位元組先後順序從存取取得時到最後處理資料的過程中都是完全一致的,那麼這個就是字元設備。換句話說,字元設備可以看作是流設備。就像鍵盤輸入資料一樣,連續敲兩個字鍵,這兩個鍵對應的位元組資料在被接收的時候一定是先敲的在前面,後敲的在後面。同理終端設備也是以一樣的,程式將資料輸出到終端機時,程式先輸出字母a再輸出數字3,那麼顯示在終端機上時一定是a在前,3在後。

以上是Linux下的檔案類型介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:cnblogs.com。如有侵權,請聯絡admin@php.cn刪除