這裡介紹 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*   # 記憶卡

block 設備檔案

使用 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/

character 設備檔案

這是從 /dev/urandom 這個 character 設備檔案讀取亂數資料的例子:

head -c16 /dev/urandom | od -A x -t x1z -v

我們從 /dev/urandom 讀取 16 個 bytes 的資料,再導向給 od 輸出:

/dev/urandom 讀取資料

/dev/zero 也是一個 character 設備檔案,而從其中讀取出來的資料都會是 0x00

head -c32 /dev/zero | od -A x -t x1z -v

/dev/zero 讀取資料

連結檔案

連結檔案就是指向其他檔案或目錄的連結,這種檔案類型在系統上也是很常見的。

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 管線檔案

有了 pipe 管線檔案之後,我們可以將 date 的輸出導入這個 pipe 管線檔案:

date > mypipe

這時候資料會被儲存至 pipe 管線檔案的緩衝區中,等待後續的行程來讀取它。

接著我們再使用 cat 將這個 pipe 管線檔案中資料讀取出來,並且輸出:

cat mypipe

這樣的效果就等同於一般的 Unix 管線,不過在程式設計上使用 pipe 管線檔案會比較方便,可讓不同的程式直接以檔案的形式互相傳遞資料。

pipe 管線檔案

Socket 檔案

socket 檔案也是用於不同行程之間溝通用的媒介,特別是在網路服務的應用上特別常見,可提供不同主機之間互相溝通的管道,而這種檔案類型絕大部分都是在程式設計時才會有機會使用到。

在 Linux 伺服器上的 /run/ 目錄中通常會有一些 socket 檔案:

ls -l /run/*sock*

socket 檔案

在開發網路通訊相關的程式時,就很常會需要建立 socket 檔案,以 C 語言來說就是使用 socket 這個函數:

int sockfd = socket(AF_INET, SOCK_STREAM, 0);

在建立好 socket 檔案之後,所有的網路資料傳輸就可以仿照存取檔案的方式處理,這部份可以參考網路上 Linux 的 socket 程式設計範例。

參考資料:TecmintLinux.comWikipediaLinux ConfigStackExchange