1. 程式人生 > >mount -o loop 迴環裝置相關

mount -o loop 迴環裝置相關

先讓我們來了解下:

迴環裝置(loop-back devices) 


迴環裝置( 'loopback device')允許使用者以一個普通磁碟檔案虛擬一個塊裝置。設想一個磁碟裝置,對它的所有讀寫操作都將被重定向到讀寫一個名為 disk-image 的普通檔案而非操作實際磁碟或分割槽的軌道和扇區。(當然,disk-image 必須存在於一個實際的磁碟上,而這個磁碟必須比虛擬的磁碟容量更大。)迴環裝置允許你這樣使用一個普通檔案。

迴環裝置以 /dev/loop0、/dev/loop1 等命名。每個裝置可虛擬一個塊裝置。注意只有超級使用者才有許可權設定迴環裝置。

迴環裝置的使用與其它任何塊裝置相同。特別是,你可以在這個裝置上建立檔案系統並像普通的磁碟一樣將它掛載在系統中。這樣的一個將全部內容儲存在一個普通檔案中的檔案系統,被稱為虛擬檔案系統(virtual file system)(譯者注:這個用法並不常見。VFS 通常另有所指,如指代 Linux 核心中有關檔案系統抽象的程式碼層次等)。


可以通過下列步驟建立一個虛擬檔案系統並通過迴環裝置掛載:

建立一個用於承載虛擬檔案系統的空檔案。這個檔案的大小將成為掛載後文件系統的大小。
建立指定大小檔案的簡單方法是通過 dd 命令。這個命令以塊為單位(通常為 512 位元組)從一個檔案向另一個檔案複製資料。/dev/zero 檔案則是一個很好的資料來源。
要建立一個 10 MB 大的名為 disk-image 的檔案可以通過以下命令:
% dd if=/dev/zero of=/tmp/disk-image count=20480
20480+0 records in
20480+0 records out
% ls -l /tmp/disk-image
-rw-rw----     1 root      root       10485760 Mar   8 01:56 /tmp/disk-image

這個新建立的檔案被填滿了 0 位元組。在掛載之前,必須在其上建立一個檔案系統。這個過程會建立許多用於組織和儲存檔案的控制單元並構造根目錄結構。
在這個磁碟映像之上可以構建任何型別的檔案系統。以建立 ext2 檔案系統為例(ext2 是 Linux 系統中最常見的檔案系統),用 mke2fs 可以完成這個操作。因為這個命令通常是針對塊裝置進行操作,當對一個普通檔案操作時它會要求確認:
% mke2fs -q /tmp/disk-image
mke2fs 1.18, 11-Nov-1999 for EXT2 FS 0.5b, 95/08/09
disk-image is not a block special device.

Proceed anyway? (y,n) y
這裡 -q 引數用於省略輸出有關新建立檔案系統的概要資訊。如果你想看到這些資訊,則請省略這個引數。
現在 disk-image 檔案包含了一個新建立的檔案系統,正如一個被剛剛初始化完畢的 10 MB 大小的磁碟。
以一個環回裝置掛載這個檔案系統。方法是使用 mount 命令,指定磁碟檔案為被掛載的裝置。同時指定 loop=loopback-device 作為 -o 選項的引數,告訴 mount 命令使用哪個迴環裝置。
下面例子中的命令可用於掛載我們的 disk-image 檔案系統。要記住的是隻有超級使用者可以使用環回裝置。第一個命令將建立一個目錄 /tmp/virtual-fs,這個目錄將被用於掛載我們的檔案系統。
% mkdir /tmp/virtual-fs
% mount -o loopback=/dev/loop0 /tmp/disk-image /tmp/virtual-fs
這時,這個裝置應該已經被掛載,就如同一個普通的 10M 空間的磁碟一樣。
% df -h /tmp/virtual-fs
Filesystem   Size Used Avail Use% Mounted on
/tmp/disk-image 9.7M 13k 9.2M 0% /tmp/virtual-fs
你可以向任何其它磁碟一樣使用這個裝置:
% cd /tmp/virtual-fs
% echo 'Hello, world!' > test.txt
% ls -l
total 19
drwxr-xr-x 2   root root 12288 Mar 8 02:00 lost+found
-rw-rw---- 1   root root     14 Mar 8 02:12 test.txt
% cat test.txt
Hello, world!
請注意 lost+found 是一個由 mke2fs 自動建立的資料夾一旦檔案系統被破壞,部分資料被回覆但沒有與任何檔案關聯起來,將被放置在這個資料夾中。。
結束使用後,解除安裝這個檔案系統:
% cd /tmp
% umount /tmp/virtual-fs
你可以刪除 disk-image,或者之後再次掛載並使用其中的檔案。你甚至可以將這個檔案複製到遠端主機並在那裡掛載、使用——檔案系統的內容完全不會受到影響。
除了從新建立一個檔案系統,還可以從一個現有的檔案系統複製而得到一份映像。例如,可以通過普通的複製操作為一個 CD-ROM 建立一份映像。

如果系統中有一個 IDE 介面的 CD-ROM 驅動器,使用前面說過的裝置名如 /dev/hda。如果 CD-ROM 是 SCSI 介面的話,裝置檔名可能是 /dev/scd0 之類。系統中也可能包含一個符號連結 /dev/cdrom 指向實際的光碟機。請參考 /etc/fstab (譯者注: 手冊)檢視系統實際使用的光碟機對應的裝置。

接下來要做的僅僅是將這個裝置複製為一個檔案——得到的檔案將是被存在硬碟上的、這個 CD-ROM 內容的完整映像。例如:

% cp /dev/cdrom /tmp/cdrom-image
取決於裝置的速度和 CD-ROM 的容量,這個操作可能需要幾分鐘的時間。最終的檔案將會相當大,它的體積與這個 CD-ROM 的容量相同。

這時,你可以在系統中掛載這個光碟而無須插入原始的 CD-ROM 碟片。要掛載在 /mnt/cdrom 目錄下:

mount -o loopback=/dev/loop0 /tmp/cdrom-image /mnt/cdrom

因為映像位於磁碟上,這個檔案系統的速度將遠勝於直接掛載自實際光碟機的時候。請注意多數光碟使用的檔案系統型別都是   iso9660。

特殊裝置
Linux 同時提供了多個並不對應於硬體的裝置檔案。這些裝置的主裝置號都是 1;這個主裝置號對應於 Linux 核心的記憶體裝置而非任何裝置驅動。

/dev/null

/dev/null 檔案,null 裝置,是一個經常被用到的裝置。它有兩個用途;通常而言,你至少熟悉其中一個用途:

Linux 會丟棄所有別寫入到 /dev/null 的資料。一個常用的技巧是將 /dev/null 作為重定向的目標檔案,以丟棄在某些情況下不需要的輸出資訊。
例如,可以像這樣執行程式並丟棄所有標準輸出(而非列印到終端或寫入檔案):
% verbose_command > /dev/null
從 /dev/null 中讀取會始終得到檔案結束標記(EOF)。例如,如果開啟一個 /dev/null 的檔案描述符並嘗試呼叫 read 讀取內容,read 將無法讀取任何資訊並直接返回 0。如果你從 /dev/null 複製到任何檔案,目標檔案將為 0 位元組長度:
% cp /dev/null empty-file
% ls -l empty-file
-rw-rw----    1 samuel    samuel       0 Mar    8 00:27 empty-file
/dev/zero

/dev/zero 裝置表現為一個具有無限長度 0 位元組的檔案。Linux 會為讀取程序生成足夠的“0”位元組返回。

為展示這點,可以執行讀資料一節中展示的程式 B.4。這個程式將以十六進位制格式輸出檔案內容。

% ./hexdump /dev/zero
0x000000 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x000010 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x000020 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x000030 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
...
當您確信它將會無休止的繼續執行下去請按下 Ctrl+C。

將 /dev/zero 通過 mmap 對映到程序地址空間是一種分配記憶體的高階技巧。參考程序間通訊一章中mmap 的其它用途以及mprotect一節中有關“獲得頁面對齊的記憶體”一段內容為例。

/dev/full

特殊檔案 /dev/full 表現為位於一個沒有剩餘空間的檔案系統上的檔案。向 /dev/full 寫入檔案將會失敗並得到 errno 錯誤號為 ENOSPC。這個錯誤一般代表著寫入的裝置已滿。

例如,你可以嘗試利用 cp 命令這樣寫入 /dev/full:

% cp /etc/fstab /dev/full
cp: /dev/full: No space left on device
/dev/full 檔案主要用於測試程式在寫入檔案時遇到空間不足情況的行為。

隨機數裝置

特殊裝置檔案 /dev/random 和 /dev/urandom 提供了對 Linux 核心內建的隨機數生成器的訪問。

多數用於生成隨機數的軟體函式,例如 C 標準庫中的   rand 函式,實際上生成的是 偽隨機數(pseudorandom numbers)。儘管這些數字符合隨機數的某些特徵,它們是可被重現的:如果以相同的種子值開始,你將始終得到同一個序列的偽隨機數。這個行為是必然的,因為計算機的本質上是確定及可預知的(deterministic and predictable)。然而,對於某些特定程式而言,這種可預知性是不被期望的;例如,有時候,如果取得加密使用的隨機數序列,破解某些加密演算法將成為可能。

程式要獲得更好的隨機數將依賴於來自於系統外的隨機性。Linux 核心捕捉了一個非常好的隨機性來源:你!通過測量使用者輸入事件(如擊鍵或滑鼠移動等)之間的時間差,Linux 可以生成一個非常好質量的、無法被預知的隨機數序列。你可以通過訪問 /dev/random 或 /dev/urandom 讀取這個數列。讀取得到的資料將是隨機生成的位元組。

這兩個裝置的區別將在 Linux 用盡已儲存的隨機數序列時體現出來。如果從 /dev/random 中讀取一個很長序列的隨機數而不產生任何輸入事件(不碰鍵盤、不移動滑鼠或做任何類似的事情),Linux 將會阻塞讀取操作。只有當你提供了某些隨機性給 Linux 時,系統才會生成更多隨機數並返回給程式。

例如,嘗試用 od 命令我們在這裡使用 od 代替行為相當接近的、B.4 中的 hexdump 命令,因為 hexdump 會在沒有資料時直接退出,而 od 會等待更多的輸入。指定的 -t x1 擦書會提示 od 以十六進位制格式輸出檔案內容。輸出 /dev/random 的內容。每行輸出將顯示 16 個隨機的位元組。

% od -t x1 /dev/random
0000000 2c 9c 7a db 2e 79 3d 65 36 c2 e3 1b 52 75 1e 1a
0000020 d3 6d 1e a7 91 05 2d 4d c3 a6 de 54 29 f4 46 04
0000040 b3 b0 8d 94 21 57 f3 90 61 dd 26 ac 94 c3 b9 3a
0000060 05 a3 02 cb 22 0a bc c9 45 dd a6 59 40 22 53 d4
你將看到的輸出的行數可能不同——可能很少——但在 Linux 耗盡儲存的隨機性資訊時,輸出最終會暫停。這個時候,嘗試移動滑鼠或在鍵盤上輸入,你將觀察到 od 會輸出一些額外的位元組。為得到更好的隨機性,讓你的貓在鍵盤上走一遭吧 :)

對比之下,對 /dev/urandom 的讀操作將不會被阻塞。如果 Linux 耗盡了隨機性資料,它會通過某種加密演算法從之前的隨機位元組序列中生成更多的偽隨機數。儘管對於很多情況來說,這樣得到的隨機數已經符合要求,仍然會有一些測試將允許 /dev/random 生成的序列通過而這個序列失敗。

舉例說明,如果你執行下面的命令,在 Ctrl+C 被按下之前你將看到無止盡的隨機字元從眼前飄過:

% od -t x1 /dev/urandom
0000000 62 71 d6 3e af dd de 62 c0 42 78 bd 29 9c 69 49
0000020 26 3b 95 bc b9 6c 15 16 38 fd 7e 34 f0 ba ce c3
0000040 95 31 e5 2c 8d 8a dd f4 c4 3b 9b 44 2f 20 d1 54
...
在程式中使用 /dev/random 的隨機數非常簡單。列表 6.1 展示了一個通過從 /dev/random 中讀取的位元組生成隨機數的函式。請記住,/dev/random 會將讀操作阻塞直到系統有足夠的隨機數提供給程式;如果對隨機數的質量的要求不那麼高而更多要求程式能快速執行,可以用 /dev/urandom 代替。

列表 6.1 (random_number.c)利用 /dev/random 的隨機數生成函式

#include <assert.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>

/* 返回MIN和MAX之間(包含MIN和MAX)的一個隨機整數。從 /dev/random獲得 隨機性。 */

int random_number (int min, int max)
{
   /* 在一個靜態變數中儲存開啟/dev/random的檔案描述符。這樣我們就不需要在每次呼叫這個函式時都開啟檔案。*/
   static int dev_random_fd = -1;
   char* next_random_byte;
   int bytes_to_read;
   unsigned random_value;

   /* 確保 MAX比MIN大。 */
   assert (max > min);

   /* 如果這是這個函式第一次被呼叫,開啟/dev/random裡的檔案描述符。*/
   if (dev_random_fd == -1) {
     dev_random_fd = open (“/dev/random”, O_RDONLY);
     assert (dev_random_fd != -1);
   }

   /* 讀足夠的隨機數來填充一個整型變數 。*/
   next_random_byte = (char*) &random_value;
   bytes_to_read = sizeof (random_value);
   /* 直到我們已經讀取了足夠的位元組時停止迴圈。因為/dev/random包含使用者動作產生的隨機數,
      讀操作也許會被阻塞並且可能一次只返回一個單個的隨機位元組。*/
   do {
     int bytes_read;
     bytes_read = read (dev_random_fd, next_random_byte, bytes_to_read);

 bytes_to_read -= bytes_read;
     next_random_byte += bytes_read;
   } while (bytes_to_read > 0);

   /*通過運算,使隨機數保持在正確範圍內。*/
   return min + (random_value % (max - min + 1));
}
迴環裝置(loop-back devices)

迴環裝置( 'loopback device')允許使用者以一個普通磁碟檔案虛擬一個塊裝置。設想一個磁碟裝置,對它的所有讀寫操作都將被重定向到讀寫一個名為 disk-image 的普通檔案而非操作實際磁碟或分割槽的軌道和扇區。(當然,disk-image 必須存在於一個實際的磁碟上,而這個磁碟必須比虛擬的磁碟容量更大。)迴環裝置允許你這樣使用一個普通檔案。

迴環裝置以 /dev/loop0、/dev/loop1 等命名。每個裝置可虛擬一個塊裝置。注意只有超級使用者才有許可權設定迴環裝置。

迴環裝置的使用與其它任何塊裝置相同。特別是,你可以在這個裝置上建立檔案系統並像普通的磁碟一樣將它掛載在系統中。這樣的一個將全部內容儲存在一個普通檔案中的檔案系統,被稱為虛擬檔案系統(virtual file system)(譯者注:這個用法並不常見。VFS 通常另有所指,如指代 Linux 核心中有關檔案系統抽象的程式碼層次等)。

可以通過下列步驟建立一個虛擬檔案系統並通過迴環裝置掛載:

建立一個用於承載虛擬檔案系統的空檔案。這個檔案的大小將成為掛載後文件系統的大小。
建立指定大小檔案的簡單方法是通過 dd 命令。這個命令以塊為單位(通常為 512 位元組)從一個檔案向另一個檔案複製資料。/dev/zero 檔案則是一個很好的資料來源。
要建立一個 10 MB 大的名為 disk-image 的檔案可以通過以下命令:
% dd if=/dev/zero of=/tmp/disk-image count=20480
20480+0 records in
20480+0 records out
% ls -l /tmp/disk-image
-rw-rw----     1 root      root       10485760 Mar   8 01:56 /tmp/disk-image
這個新建立的檔案被填滿了 0 位元組。在掛載之前,必須在其上建立一個檔案系統。這個過程會建立許多用於組織和儲存檔案的控制單元並構造根目錄結構。
在這個磁碟映像之上可以構建任何型別的檔案系統。以建立 ext2 檔案系統為例(ext2 是 Linux 系統中最常見的檔案系統),用 mke2fs 可以完成這個操作。因為這個命令通常是針對塊裝置進行操作,當對一個普通檔案操作時它會要求確認:
% mke2fs -q /tmp/disk-image
mke2fs 1.18, 11-Nov-1999 for EXT2 FS 0.5b, 95/08/09
disk-image is not a block special device.
Proceed anyway? (y,n) y
這裡 -q 引數用於省略輸出有關新建立檔案系統的概要資訊。如果你想看到這些資訊,則請省略這個引數。
現在 disk-image 檔案包含了一個新建立的檔案系統,正如一個被剛剛初始化完畢的 10 MB 大小的磁碟。
以一個環回裝置掛載這個檔案系統。方法是使用 mount 命令,指定磁碟檔案為被掛載的裝置。同時指定 loop=loopback-device 作為 -o 選項的引數,告訴 mount 命令使用哪個迴環裝置。
下面例子中的命令可用於掛載我們的 disk-image 檔案系統。要記住的是隻有超級使用者可以使用環回裝置。第一個命令將建立一個目錄 /tmp/virtual-fs,這個目錄將被用於掛載我們的檔案系統。
% mkdir /tmp/virtual-fs
% mount -o loopback=/dev/loop0 /tmp/disk-image /tmp/virtual-fs
這時,這個裝置應該已經被掛載,就如同一個普通的 10M 空間的磁碟一樣。
% df -h /tmp/virtual-fs
Filesystem   Size Used Avail Use% Mounted on
/tmp/disk-image 9.7M 13k 9.2M 0% /tmp/virtual-fs
你可以向任何其它磁碟一樣使用這個裝置:
% cd /tmp/virtual-fs
% echo 'Hello, world!' > test.txt
% ls -l
total 19
drwxr-xr-x 2   root root 12288 Mar 8 02:00 lost+found
-rw-rw---- 1   root root     14 Mar 8 02:12 test.txt
% cat test.txt
Hello, world!
請注意 lost+found 是一個由 mke2fs 自動建立的資料夾一旦檔案系統被破壞,部分資料被回覆但沒有與任何檔案關聯起來,將被放置在這個資料夾中。。
結束使用後,解除安裝這個檔案系統:
% cd /tmp
% umount /tmp/virtual-fs
你可以刪除 disk-image,或者之後再次掛載並使用其中的檔案。你甚至可以將這個檔案複製到遠端主機並在那裡掛載、使用——檔案系統的內容完全不會受到影響。
除了從新建立一個檔案系統,還可以從一個現有的檔案系統複製而得到一份映像。例如,可以通過普通的複製操作為一個 CD-ROM 建立一份映像。

如果系統中有一個 IDE 介面的 CD-ROM 驅動器,使用前面說過的裝置名如 /dev/hda。如果 CD-ROM 是 SCSI 介面的話,裝置檔名可能是 /dev/scd0 之類。系統中也可能包含一個符號連結 /dev/cdrom 指向實際的光碟機。請參考 /etc/fstab (譯者注: 手冊)檢視系統實際使用的光碟機對應的裝置。

接下來要做的僅僅是將這個裝置複製為一個檔案——得到的檔案將是被存在硬碟上的、這個 CD-ROM 內容的完整映像。例如:

% cp /dev/cdrom /tmp/cdrom-image
取決於裝置的速度和 CD-ROM 的容量,這個操作可能需要幾分鐘的時間。最終的檔案將會相當大,它的體積與這個 CD-ROM 的容量相同。

這時,你可以在系統中掛載這個光碟而無須插入原始的 CD-ROM 碟片。要掛載在 /mnt/cdrom 目錄下:

mount -o loopback=/dev/loop0 /tmp/cdrom-image /mnt/cdrom
因為映像位於磁碟上,這個檔案系統的速度將遠勝於直接掛載自實際光碟機的時候。請注意多數光碟使用的檔案系統型別都是   iso9660。