home products tech support contact us

 Linux 技術支援    ⇒   基礎篇    進階篇    補腦篇    指令索引    中⇒ENG
版權所有, 引用請註明出處

 虛擬儲存裝置

1.0 虛擬儲存裝置~色不異空,空不異色
        dd 實體轉虛擬
        losetup 虛擬轉實體
            kpartx 映射映像檔 partition 到 loop-device
1.1 swap 輔助記憶體
       swap-partition
           swapon 啟用 swap
           swapoff 禁能 swap
       swap-file
           mkswap 格式化 swap
       swappiness 使用 swap 的積極度


 1.0 虛擬儲存裝置~色不異空,空不異色
如果 user 有用過虛擬機安裝 Linux,會覺得虛擬的〝東西〞如幻似真虛實難辨。一整個作業系統都可虛擬所以虛擬儲存裝置如光碟,硬碟,filesystem 等對 Linux 來說簡直是雕蟲小技,且 Linux 也內建許多虛實互換的工具。

UXIN/Linux 的哲學〝 Everything is a file〞(一切都是檔案) 而關鍵是那個〝檔案〞,檔案也可視為實體儲存裝置如〝/dev/sda〞,故 Linux 的檔案和實體裝置之間只有一線之隔,懂的虛實互換會有無限的可能 。

心經說[色不異空,空不異色],〝色〞指的的實體的東西,〝空〞是虛擬旳,白話的解釋就是[虛、實是一樣的]。UXIN/Linux 的世界實體儲存裝置和虛擬的〝檔案裝置〞(device file)也是〝色即是空,空即是色〞,。


dd 實體轉虛擬
在 Windows 下要把光碟轉 iso 檔常用〝WinISO〞 或〝 UltraIOS〞 等工具,完整複製硬碟可能會用收費的商用軟體〝Norton GHOST 〞或〝Acronis True Image〞等。 相對的 Linux 下有一廟小妖風大的工具 dd 就有上述那些工具大部份的功能且免費!! 唯一不及就是不能用滑鼠來操作,奇怪的是這麼強大功能的軟體其名稱〝 dd〞怎麼來的眾說紛紜。

dd
主要是讀取資料並轉換有點類似 tr,如下例。

例:
$ cat fileA | dd conv=ucase > fileB ←將 fileA 內小寫改大寫存入 fileB

參數〝conv=ucase〞小寫改大寫,相反的參數〝conv=lcase〞大寫改小寫。

dd
除了經管線重定向操作也可用〝if=〞(input file)來讀入檔案和用〝of=〞(ontput file)寫入檔案。

例:
$ dd if=fileA of=fileB conv=lcase ←將 fileA 內大寫改小寫存入 fileB

表面上 dd 功能普普通通,但 dd 轉換的不只有字元,可實體轉虛擬由色轉空, dd 可轉換實體裝置成虛擬裝置檔(此種檔案叫〝 image-file〞或〝映像檔〞)將來有需要時可把 image-file 當實體的媒體看待。

如下例把實體裝置 CD-ROM (Centos 7 的安裝光碟)轉成虛擬的 image-file (iso 檔)。

例:
$ isoinfo -d -i /dev/cdrom ←讀取 CDROM 資訊
CD-ROM is in ISO 9660 format
System id: LINUX
Volume id: CentOS 7 x86_64
Volume set id:
Publisher id:
Data preparer id:
Application id: GENISOIMAGE ISO 9660/HFS FILESYSTEM CREATOR (C) 1993 E.YOUNGDALE
Copyright File id:
Abstract File id:
Bibliographic File id:
Volume set size is: 1
Volume set sequence number is: 1
Logical block size is: 2048
Volume size is: 2182204
以下略

以上利用 isoinfo 所輸出的資訊可看出此張光碟的格式為 iso-9660, Logical block size 是 2048 以及 Volume size 是 2182204 。
以下是根據 isoinfo 的資訊用 dd 指令將光碟轉成 .iso 檔案。

$ dd if=/dev/cdrom of=centos7.iso bs=2048 count=2182204 status=progress
4422363136 bytes (4.4 GB, 4.1 GiB) copied, 57 s, 77.6 MB/s
2182204+0 records in
2182204+0 records out 4469153792 bytes(4.5 GB,4.2 GiB)copied,60.7711 s, 73.5 MB/s

上例參數〝bs〞為讀/寫 block 的大小,如沒指定〝bs〞 大小預設為 512 byte。(如有指定〝bs〞大小,此時會蓋過讀取 block 大小的參數〝ibs〞和寫入 block 大小的參數〝obs〞。)最後 最好加上 status=progress 參數,可以顯示轉換的進度。

同理 dd 也可用來把實體 partition 或軟碟等轉成映像檔 。

例:

# dd if=/dev/sda5 of=sda5.img ←將 partition 轉 image-file
# dd if=/dev/fd0 of=floppy2.img ←將軟碟轉 image-file
# dd if=floppy2.img of=/dev/fd0 ←還原 image-file 檔到軟碟

建立了 image-file後,以後要使用該媒體可不用真的用實體光碟或軟碟,就用掛載虛擬裝置或用和 dd 反動作的 losetup 就可以了。

IT 的人員一定用過 Norton Ghost(諾頓魅影系統)來複製/備份 Windows 系統,用 dd 就可取代那個需付費的〝鬼〞軟體。

例:
# dd if=/dev/sda of=/dev/sdb conv=noerror ←硬碟複製
# dd if=/dev/sda conv=noerror | gzip -c > win_xp.img.gz ←用壓縮的映像檔備份硬碟
# gzip -dc win_xp.img.gz | dd of=/dev/sda ←用 image-file 還原回硬碟
上例中的參數〝conv=noerror〞為如果讀取有誤照讀不管,如確定不會有錯誤產生可略此參數。

有時可能因中毒或不明原因硬碟重要的 MBR GPT table 損壞而使系統無法開機, dd 廟小妖風大也可用來製作還魂丹,備份硬碟記載開機和 partition 的 MBR/ GPT table,可用來災害復原(Disaster Recovery)。

MBR 記錄在硬碟一開頭的前 512 Byte, 備份和還原 MBR 範例如下:

例:
# dd if=/dev/sdb of=mbr bs=512 count=1 ←備份 MBR table
# dd if=mbr of=/dev/sdb bs=512 count=1 ←還原 MBR table
上例中〝bs=512〞,因 MBR table 只用 512 Byte 來記錄,而參數〝count〞為執行多少次數的 block-size。

如要用 dd 備份GPT table ,只要備份前 34 個 LBA 即可,GPT scheme 如下表::(512e 或傳統硬碟一個 LBA=block=512B)

CUID Partition Table (GPT) Scheme
LBA 0 Protective MBR  
LBA 1 Primary GPT Header Primary GUID Partition Entry Array
LBA 2 GUID Partition entries 1~4
LBA 3 GUID Partition entries 5~8
¦ ¦
LBA 32 GUID Partition entries 121~124
LBA 33 GUID Partition entries 125~128
LBA 34 Partition 1 Partition or unused area
¦ ¦
LBA N Partition 2
   
[註 1.0]。

例:
# dd if=/dev/sdc of=gpt bs=512 count=34 ←備份 primary gpt table
# dd if=gpt of=/dev/sdc bs=512 count=34 ←還原 primary gpt table

dd 也常用來徹底清除硬碟資料,因 mkfs 格式化 ext2/ext3/ext4 partition 時只會重建 inode 不會去清除 block,所以有心人或許有辦法復原其內容,故如用 dd if=/dev/zero of=/dev/sda 把〝/dev/zero〞塞滿整顆硬碟應就沒有人有辦法還原了 。

dd 也時常用來產生〝 空〞的映像檔 ,但〝真空妙有〞,此檔要作什可千變萬化,如產生 swap-file 當 swap partition 或如下例當虛擬 partition ,經格式化後可掛載不用分割硬碟就莫明奇妙多一 partition,有時沒多餘的硬碟或不想冒險分割現有硬碟但需要額外的 partition 空間時還蠻方便的,如下例操作。

例:
# dd if=/dev/zero of=200M-image bs=200M count=1 ←產生一個 200M 的內容是空的映像檔
# mkfs 200M-image ←格式化此映像檔
mke2fs 1.40.2 (12-Jul-2007)
200M-image is not a block special device. ←會出現此檔非〝block device〞(儲存裝置)的警告
Proceed anyway? (y,n) y ←不管警告按<y>繼續格式化
# mount -t ext2 -o loop 200M-image /mnt ←掛載此虛擬 partition

有必要時可加入〝/etc/fstab〞讓一開機就掛載。上例操作轉換裝置成檔案,其裝置〝/dev/zero〞為一特殊裝置內容是〝無〞。

映像檔大小為〝bs x count〞,可接受 KB(1000), K(1024), MB (1000*1000),M(1024*1024) 和 GB,G 或 TB,T 等單位,上例〝bs=200M count=1〞 和〝bs=1 count=200M〞大小是一樣的但前者速度快很多,因後者〝count=200M〞要重複 200M 次。

而最有效率的寫法為 dd if=/dev/zero of=200M-image obs=1 count=0 seek=200M,因 count=0 故不論產生多大的檔案皆瞬間完成。參數〝seek〞為 offset(位移)多少倍數的〝obs 〞才寫入檔案,其相反的參數〝skip〞為 offset 多少倍數的〝ibs〞才讀入檔案。這種空的映像檔不只當 partition,也可用 parted image-file 當硬碟來分割。

dd 會順便統計執行時間,故也時常用來測試硬碟的速度,如下例分別測試讀/寫的速度。

例:
# dd if=/dev/zero bs=1024 count=1000000 of=1G-file ←測試寫的速度(block=1k 大小為 1G)
# dd if=1G-file bs=1024 of=/dev/null ←測試讀的速度

上例時常來判斷那種 block 大小最有效率供格式化時指定 block 大小的參考。

^ back on top ^

losetup 虛擬轉實體
為什用 dd 製造的檔案又不是 partition 卻可用 mount 來掛載?在掛載時用選項〝-v〞來觀察.如下動作範例。

例:
# mount -v -t ext2 -o loop 200M-image /mnt ←mount 時加入選項〝-v〞
mount: going to use the loop device /dev/loop0 ←使用 loop device ??
/root/200M-image on /mnt type ext2 (rw,loop=/dev/loop0)

mount -v -o loop 來掛載映像管檔會出現使用〝 loop device〞 什麼是〝 loop device〞?〝 loop device〞是虛擬儲存設備,〝 loop device〞,一般預設有 8 個從〝/dev/loop0〞到〝/dev/loop7〞(不同發行版所支援的 loop device 上限數會有不同)但不能直接使用,因還沒指定檔案裝置(映像檔)給 loop device。指定檔案裝置給 loop device 的工具是 losetup(loop device setup)。

losetup 用法為 losetup [-option] [/dev/loop#] device(# 為數字),例如 losetup /dev/loop0 200M-image 。此時〝 /dev/loop0〞 這個虛擬設備檔會成為映像檔的附體,而系統對虛擬儲存設備檔〝/dev/ loop#〞是真假不分以為就是真的儲存設備,操作起來和實體儲存裝置一模一樣。

而操作 mount -o loop 這動作實際上是在背後執行了losetup,如不用mount -o loop 來掛載分解動作如下例:

例:
# losetup /dev/loop0 200M-image ←將映像檔指定給虛擬設備檔〝/dev/loop0〞
# mount -t ext2 /dev/loop0 /mnt ←掛載〝/dev/loop0〞

如要解除 losetup 和映像檔之間的關連為選項〝-d〞,如 losetup -d /dev/loop0 會分離〝/dev/loop0〞和映像檔之間的關連。

而選項〝 -v〞會顯示 loop device 有無和映像檔有關連,如 losetup -v /dev/loop3 或用 losetup -a 掃描〝/dev/loop0〞~〝/dev/loop7〞。另一選項〝 -f〞會找出下一個沒使用的 loop-device 就不用指定 loop-device。

例:
# losetup -a ←掃描使用了那些 loop-device
/dev/loop0: [0805]:261784 (disk-image) ←〝/dev/loop0〞使用中
# losetup -fv part-image ←自動為檔案〝part-image〞找下一個沒使用的 loop-device
Loop device is /dev/loop1 ←自動找到〝/dev/loop1〞

在介紹 dd 時有示範一產生一空的映像檔後就立刻拿來格式化會有〝not a block special device〞的警告,因用 dd 所產生空的映像檔〝假裝〞的儲存裝置假假的一下就被識破(雖可繼續操作)。如果此一空的映像檔用 losetup 來包裝一下就會裝的很像很像達到真假難辨的最高境界,用 blkid 會被當儲存媒體列出,如下的範例操作。

例:
# dd if=/dev/zero of=disk-image bs=100M count=1 ←產生 100M 空的映像檔
# losetup /dev/loop0 disk-image ←將映像檔模擬成硬碟 partition

losetup 後操作〝/dev/loop0〞後此 loop-device 和真的硬碟沒兩樣,用 mkfs /dev/loop0 來格式化時不再有直接格式化 image-file 會出現〝not a block special device〞的警告也可用 fdisk /dev/loop0 當硬碟分割(如 image-file 超過 2T 要用 parted 操作)。

以上實驗可知 losetup 是把虛擬的 image-file 轉實體的裝置由空轉色。經 dd 配合 losetup 施以虛實乾坤大法莫明就多了 8 顆硬碟(〝/dev/loop0〞~〝/dev/loop7〞),也不用煩惱多出那麼多的硬碟該如何處理有空可用來玩玩 LVM 和 RAID 就不怕把系統搞垮。

如果我用 dd 備份分割了好幾個 partition 的硬碟,如要個別分離 partition 要用位移(offset) 選項〝 -o〞。如下為一映像檔分割了三個 partition 範例。
# fdisk -l disk-image ←列出 image-file 的 partition
Device Boot      Start         End      Blocks   Id  System
disk-image1               1         320       20464    c  W95 FAT32 (LBA)
disk-image2             321         800       30720   83  Linux
disk-image3             801        1600       51200   82  Linux swap / Solaris

當 image-file 有一個以上的 partition 如沒用選項〝 -o〞不但不能正確的使用,如有存取 image-file 動作還可能會導致 image-file 損壞。

因選項〝 -o〞offset 的單位是 byte, 故可利用 parted 自動轉換單位為 byte 供 losetup -o 的位移值來使用,如下用操作。

# parted disk-image unit B print ←例出 partition 起始 byte

Number  Start      End         Size       Type     File system  Flags
1      16384B     20971519B   20955136B  primary               lba 
2      20971520B  52428799B   31457280B  primary                   
3      52428800B  104857599B  52428800B  primary

上例中 partition #1~#3 起始 byte 各為 16384,20971520 和 52428800,為 partition offset (位移)的值,故可如下操作讓 loop device 對應這三個 partition。

例 :
# losetup -o 16384 /dev/loop0 disk-image ←〝/dev/loop0〞 對應 partition1
# losetup -o 20971520 /dev/loop1 disk-image ←〝/dev/loop1〞 對應 partition2
# losetup -o 52428800 /dev/loop2 disk-image ←〝/dev/loop2〞 對應 partition3

或如下操作:
# losetup /dev/loop0 disk-image ←以〝/dev/loop0〞 當 offset 基準
# losetup -o 16384 /dev/loop1 /dev/loop0 ←〝/dev/loop1〞 對應 partition1
# losetup -o 20971520 /dev/loop2 /dev/loop0 ←〝/dev/loop2〞 對應 partition2
# losetup -o 52428800 /dev/loop3 /dev/loop0 ←〝/dev/loop3〞 對應 partition3

或利用 mount 時才 offset,如下例子。
# losetup /dev/loop0 disk-image ←以〝/dev/loop0〞 當 offset 基準
# mount -o loop,offset=16384 /dev/loop0 /mnt/disk1 ←mount 時 offset
# mount -o loop,offset=20971520 /dev/loop0 /mnt/disk2
# mount -o loop,offset=52428800 /dev/loop0 /mnt/disk3

mount -o loop 實際上是在背後偷偷執行了 losetup,所以會動用額外 loop-device (可 losetup -a 掃描一下 loop-device 使用情形) 經正確的 offset 處理後,〝 /dev/loop0〞~〝 /dev/loop2〞就可虛擬 image-file 的 3 個 partition。

partition 的 offset 值也可用 fdisk 列出 sector 值來計算,如下例。

例 :
# fdisk -lu disk-image ←列出 partition 起始 sector
Units = sectors of 1 * 512 = 512 bytes ←一個 sector =512 bytes

Device Boot      Start         End      Blocks   Id  System
disk-image1              32       40959       20464    c  W95 FAT32 (LBA)
disk-image2           40960      102399       30720   83  Linux
disk-image3          102400      204799       51200   82  Linux swap / Solaris   

fdisk -lu 輸出是 sector,(硬碟一個 sector = 512 Byte,MO 碟片一個 sector 可能為 2048 或 512 bytes,注意 fdisk -lu 的〝 Units〞輸出資訊), 以 partition #1 為例啟始 sector 為 32,故 partition #1 啟始的 byte =32 x 512=16384 其結果應和 parted DEVICE unit B print 輸出一致。



^ back on top ^



 1.1 swap 輔助記憶體
相信大家都有這種經驗,操作 Windows 時如應用程式跑太多或某應用軟體大臃腫,此時 Windows 反應越來越慢只見碟碟指示的 LED 一直閃不停,這時八成是因記憶體不足時 Windows 動用了硬碟當輔助記憶體。
Windows 用硬碟當輔助記憶體叫〝Paging〞(分頁), 但傳統的機械硬碟其速度至少比記憶體慢 1000 倍,故作業系統不得已動用硬碟當輔助記憶體時光速會變龜速,但總比當掉或不能跑好,是不得已的妥協。

Unix/Linux 類似的技術叫〝swap〞,swap 為利用硬碟的空間當暫時的記憶體,是用空間交換時間,但到底需不需 swap 或 swap 要設多大一直是爭議的議題。一般來說系統記憶體愈大,愈不會發生記憶體不足而動用到 swap 空間故 swap 可設小一點,反之則 swap 可設大一點。且如有用到〝休眠〞(hibernate)因會把記憶體的資料寫入硬碟,故此時 swap 最少要大於記憶體的大小。

Linux 商業發行版龍頭 redhat 建議 swap 最少 256M 以上,如硬碟容量許可建議的 swap 大小如下:

系統記憶體 建議 swap 大小 如有休眠功能,建議 swap 大小
< 2GB 二倍系統記憶體大小 三倍系統記憶體大小
2GB-8GB 等於系統記憶體大小 二倍系統記憶體大小
8GB-64GB 系統記憶體大小 1.5倍系統記憶體大小
>64GB 4G  4G
[註 1.1]

傳統上 swap 空間用 partiton,當代的 Linux 也可和 Windows 的分頁一樣用檔案, 各用其優劣點, swap-partition 效能比較高但要變更大小比較麻煩,反之 swap-file 效能可能比較差(因檔案如太大 block 可能不是連續的空間)但要變更 swap 的大小比較方便。我怎知系統有無打開 swap 或 swap 大小?看 swapon -s (同等 cat/proc/swaps )的輸出報告就知道了。

例:
# swapon -s ←列出 swap 使用情形
Filename                                Type            Size    Used    Priority
/dev/sda3                               partition       1020116 1088    -1

上例中顯示 swap 空間為 partition,大小為 1G 。Used 為 swap 空間的使用情形,如為 0 表示還沒動到 swap,試者多人登入,進入 GUI 跑多點吃記憶軟的軟體如 office//瀏覽器或圖形編輯應可看到動用到 swap 空間。


^ back on top ^





[註1.0] 參考來源Wikipedia http://en.wikipedia.org/wiki/GUID_Partition_Table

[註1.1] 參考來源 https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Installation_Guide/s2-diskpartrecommend-x86.html