這裡介紹 Linux 「所有的東西都是檔案」的概念,以及各種檔案類型與使用範例。
在 Linux 系統上所有的東西都是以檔案的方式在處理的,各種檔案儲存在系統根目錄 /
之下的階層式目錄架構中,在整個檔案系統上有各式各樣不同的檔案類型,除了我們熟知的一般檔案與目錄之外,還有連結檔、socket、管線檔(pipe)、硬體設備檔等各種軟硬體的資源。
所有的東西都用檔案的形式管理,有一個好處就是使用方式非常統一,並且可以使用同一套工具與 API,處理各式各樣的輸入與輸出。
在 Linux 中我們可以使用 ls -l
指令來判斷檔案類型,其輸出中每一行的第一個字元就代表檔案的類型,主要有以下幾種:
ls -l 輸出第一個字元 |
說明 |
---|---|
- |
一般檔案。 |
d |
目錄。 |
b |
block 設備檔案。 |
c |
character 設備檔案。 |
l |
連結檔案。 |
p |
pipe 管線檔案。 |
s |
socket 檔案。 |
以下是每一種檔案類型的詳細介紹。
一般檔案與目錄
一般檔案是最常見的檔案類型,包含文字檔、二進位檔、圖片檔、影片檔、壓縮檔等等,這些都是屬於一般檔案的類型。
而大家所熟知的目錄在 Linux 中也是一種特別的檔案,其作用就是用來放置別的檔案或目錄,架構出整個檔案系統的目錄結構。
一般檔案在 ls -l
的輸出中,是以 -
表示,而目錄的話則是以 d
表示:
ls -l /etc/
關於一般檔案與目錄的指令非常多,以下是比較常用的幾種:
touch myfile # 建立檔案 date > myfile # 建立檔案 rm myfile # 刪除檔案 mkdir myfolder # 建立目錄 rmdir myfolder # 刪除目錄
Block 設備檔案
block 設備檔案是用來存取硬體設備的媒介,它的特性跟一般的檔案差不多,具有記憶體緩衝區的功能,可以將一個區塊的資料放在快取記憶體中進行存取,最後以整個資料區塊的方式寫入硬體設備中,所以稱為 block 設備檔案。
block 設備檔案通常也都是可查找的(seekable),也就是可以存取其中任意的位置的資料。
在 /dev
中的硬碟與記憶卡就是最典型的 block 設備檔案:
ls -l /dev/sd* # 硬碟、隨身碟 ls -l /dev/mmc* # 記憶卡
在使用 dd
指令將 ISO 檔製作成 Live USB 隨身碟時,就會使用到 block 設備檔案,另外若要清空硬碟、隨身碟或記憶卡時,也可以使用 dd
來處理,例如使用 0x00
清空整個硬碟:
dd if=/dev/zero of=/dev/sdb bs=4096
或是使用亂數填滿整個硬碟,以達到資料銷毀的目的:
dd if=/dev/urandom of=/dev/sdb bs=4096
Character 設備檔案
character 設備檔案也是一種用來存取硬體設備的媒介,不過它的特性與 block 設備檔案不太一樣,character 設備檔案比較類似管線(pipe)或序列埠(serial port)的概念,資料的輸入與輸出都是立即性的,沒有緩衝區,這種設備檔案在處理資料時都是一個字元接著一個字元依序處理的,所以稱為 character 設備檔案。
設備對於資料的處理方式是由其對應的驅動程式所負責,寫入資料至不同設備,會有不同的功用,例如讓喇叭產生聲音、輸出訊息至螢幕或序列埠;從設備讀取資料也有各種不同的情況,例如產生亂數等。
在 /dev
中的設備檔案大多是都是屬於 character 設備檔案:
ls -l /dev/
這是從 /dev/urandom
這個 character 設備檔案讀取亂數資料的例子:
head -c16 /dev/urandom | od -A x -t x1z -v
我們從 /dev/urandom
讀取 16 個 bytes 的資料,再導向給 od
輸出:
/dev/zero
也是一個 character 設備檔案,而從其中讀取出來的資料都會是 0x00
:
head -c32 /dev/zero | od -A x -t x1z -v
連結檔案
連結檔案就是指向其他檔案或目錄的連結,這種檔案類型在系統上也是很常見的。
ls -l /etc/rc5.d
連結檔案對於一般使用者來說也是很常用的,以下是建立連結檔案的指令:
ln -s target link_name
這樣就會建立一個 link_name
連結檔案,而其內容就是指向 target
這個檔案。
Pipe 管線檔案
pipe 管線檔案就是一種讓兩個行程(process)之間可以傳遞資料的媒介,其特性就跟 Unix 的管線(pipe)相同,從一個行程讀取資料之後,再把資料傳送給另外一個行程,只不過它是以有名稱的檔案來提供資料導向的功能。
我們以一個最簡單的範例來說明 pipe 管線檔案如何使用,首先來看一個普通的管線範例,這裡我們將 date
的輸出透過管線導向至 cat
,然後輸出至標準輸出:
date | cat
接著我們將是範利用 pipe 管線檔案來達到相同的效果,首先使用 mkfifo
建立一個 pipe 管線檔案:
mkfifo mypipe ls -l mypipe
有了 pipe 管線檔案之後,我們可以將 date
的輸出導入這個 pipe 管線檔案:
date > mypipe
這時候資料會被儲存至 pipe 管線檔案的緩衝區中,等待後續的行程來讀取它。
接著我們再使用 cat
將這個 pipe 管線檔案中資料讀取出來,並且輸出:
cat mypipe
這樣的效果就等同於一般的 Unix 管線,不過在程式設計上使用 pipe 管線檔案會比較方便,可讓不同的程式直接以檔案的形式互相傳遞資料。
Socket 檔案
socket 檔案也是用於不同行程之間溝通用的媒介,特別是在網路服務的應用上特別常見,可提供不同主機之間互相溝通的管道,而這種檔案類型絕大部分都是在程式設計時才會有機會使用到。
在 Linux 伺服器上的 /run/
目錄中通常會有一些 socket 檔案:
ls -l /run/*sock*
在開發網路通訊相關的程式時,就很常會需要建立 socket 檔案,以 C 語言來說就是使用 socket
這個函數:
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
在建立好 socket 檔案之後,所有的網路資料傳輸就可以仿照存取檔案的方式處理,這部份可以參考網路上 Linux 的 socket 程式設計範例。
參考資料:Tecmint、Linux.com、Wikipedia、Linux Config、StackExchange