Linux運維之道(14)——Linux文件系統管理

@(Linux)[文件系統管理]


1. 文件系統

1.1 各個操作系統上的文件系統

Linux文件系統

  • ext2
  • ext3
  • ext4
  • xfs
  • btrfs
  • reiserfs
  • jfs
  • swap(交換分區)
  • iso9660(光盤)

Windows

  • fat32
  • ntfs

Unix

  • FFS
  • UFS
  • JFS2

網絡文件系統

  • NFS
  • CIFS

集群文件系統

  • GFS2
  • OCFS2

分布式文件系統

  • ceph
  • moosefs
  • mogilefs
  • GlusterFS
  • Lustre

1.2 文件系統劃分

根據其是否支持"journal"功能

  • 日志型文件系統: ext3, ext4, xfs, ...
  • 非日志型文件系統: ext2, vfat, ...

文件系統的組成部分
內核中的比用戶控件的效率高

  • 內核中的模塊:ext4, xfs, vfat
  • 用戶空間的管理工具:mkfs.ext4, mkfs.xfs, mkfs.vfat

Linux的虛擬文件系統

  • VFS

1.3 幾種文件系統介紹

第一種文件系統:ext4

近年來 ext2/3 暴露出了一些擴展性問題,于是便催生了 ext4 。在 2008 年發布的 Linux2.6.19 內核中集成了 ext4 的 dev 版本。 2.6.28 內核發布時,ext4 結束了開發版,開始接受用戶的使用。

  • 功能

    • 向后和向前兼容性
      • ext4 與 ext3 是向前兼容的,這樣就可以將 ext3 文件系統掛載為 ext4 文件系統。
      • 為了充分利用 ext4 的優勢,必須實現文件系統的遷移,以轉換和利用新的 ext4 格式。
    • 提高時間戳分辨率和擴展范圍
      • 基于秒的時間戳已經不夠用,ext4設計時間戳時考慮到未來的發展,它將時間戳的單位提升到納秒。
      • ext4 給時間范圍添加了兩個位,從而讓時間壽命再延長 500 年。
  • 伸縮性

    • 突破文件系統的限制
      • ext4 支持的最大文件系統為 1 EB(1000 PB)。
      • ext4 支持最大 16 TB 的文件(假設由 4KB 的塊組成),這個容量是 ext3 的 8 倍。
    • 區段
      • ext4 使用區段取代 ext3 的機制,從而改善了空間的分配,并且支持更加高效的存儲結構。
      • 區段 是一種表示一組相鄰塊的方式。使用區段減少了元數據,因為區段維護關于一組相鄰塊的存儲位置的信息(從而減少了總體元數據存儲),而不是一個塊的存儲位置的信息。
      • ext4 的區段采用分層的方法高效地表示小文件,并且使用區段樹高效地表示大文件。
  • 性能

    • 文件級預分配
      • 盡管區段能夠將相鄰塊劃分為片段,但另一種更強大的方法是按照所需的大小預分配比較大的相鄰塊(XFS 以前就是采用這種方法)。
      • ext4 通過一個新的系統調用來實現這個目的,這個調用將按照特定的大小預分配并初始化文件。然后,您就可以寫入必要的數據,并為數據提供不錯的讀性能。
    • 延遲塊分配
      • 這種優化的關鍵是延遲物理塊的分配,直到需要在磁盤上寫這些物理塊時才對其進行分配并寫到相鄰的塊。
      • 這類似于持久化預分配,惟一的區別是文件系統會自動執行這項任務。不過如果預先知道文件的大小時,持久化預分配是更好的選擇。
    • 多個塊分配
      • 相鄰塊相關的優化,即針對 ext4 的塊分配器。
      • ext4 使用塊分配器修復了這個問題,它能夠在磁盤上一次分配多個塊。與前面其他優化一樣,這個優化在磁盤上收集相關的數據,以實現相鄰讀優化。
  • 可靠性

    • 執行文件系統日志校驗和
      • 和 ext3 一樣,ext4 也是一個日志文件系統。日志記錄 就是通過日記(磁盤上相鄰區域的專門循環記錄)記錄文件系統的變更的過程。
      • 但是即使進行日志記錄,如果日志出現錯誤仍然會導致文件系統損壞。為了解決這個問題,ext4 對日志執行校驗和,確保有效變更能夠在底層文件系統上正確完成。
      • ext4 支持根據用戶需求采用多種模式的日志記錄。例如,ext4 支持 Writeback 模式,它僅記錄元數據;或 Ordered 模式,它記錄元數據,但寫為元數據的數據是從日志中寫入的;或 Journal 模式(最可靠的模式),它同時記錄元數據和數據。注意,雖然 Journal 模式是確保文件系統一致的最佳選擇,但它也是最慢的,因為所有數據都要經過日志。
    • 在線磁盤碎片整理
      • 盡管 ext4 添加一些特性來減少文件系統的碎片(比如將相鄰塊分配為區段),但隨著系統使用時間的增加,碎片是難以完全避免的。因此出現了在線碎片整理工具,它們可以對文件系統和單個文件執行碎片整理,從而改善性能。在線碎片整理程序是一個簡單的工具,它將文件復制到引用相鄰區段的新 ext4 inode。
      • 在線碎片整理還可以減少檢查文件系統所需的時間(fsck)。ext4 將未使用的塊組標記到 inode 表中,并讓 fsck 進程忽略它們以加快檢查速度。當操作系統因內部損壞(隨著文件系統變大,這是不可避免的)而檢查文件系統時,ext4 的設計方式將能夠提高總體可靠性。

Note: 點擊這里,查看參考文章

第二種文件系統:btrfs

文件系統似乎是內核中比較穩定的部分,多年來,人們一直使用 ext2/3,ext 文件系統以其卓越的穩定性成為了事實上的 Linux 標準文件系統。似乎 ext 就將成為 Linux 文件系統的代名詞。然而當您閱讀很多有關 ext4 的文章時,會發現都不約而同地提到了 btrfs,并認為 ext4 將是一個過渡的文件系統。

  • 擴展性相關的特性

    • B-Tree
      • btrfs 文件系統中所有的 metadata 都由 BTree 管理。
        • 使用 BTree 的主要好處在于查找,插入和刪除操作都很高效。可以說 BTree 是 btrfs 的核心。
    • 基于 Extent 的文件存儲
      • 現代很多文件系統都采用了 extent 替代 block 來管理磁盤。
      • Extent 就是一些連續的 block,一個 extent 由起始的 block 加上長度進行定義。Extent 能有效地減少元數據開銷。
    • 動態 inode 分配
      • 在 ext2 中 inode 區是被預先固定分配的,且大小固定,比如一個 100G 的分區中,inode table 區中只能存放 131072 個 inode,這就意味著不可能創建超過 131072 個文件,因為每一個文件都必須有一個唯一的 inode 。
      • 為了解決這個問題,必須動態分配 inode 。每一個 inode 只是 BTree 中的一個節點,用戶可以無限制地任意插入新的 inode,其物理存儲位置是動態分配的。所以 btrfs 沒有對文件個數的限制。
    • 針對 SSD 的優化支持
      • SSD 采用 flash memory 技術,內部沒有磁盤磁頭等機械裝置,讀寫速率大幅度提升。 flash memory 有一些不同于 HDD 的特性。 flash 在寫數據之前必須先執行擦除操作;其次,flash 對擦除操作的次數有一定的限制,在目前的技術水平下,對同一個數據單元最多能進行約 100 萬次擦除操作,因此,為了延長 flash 的壽命,應該將寫操作平均到整個 flash 上。
      • 雖然 SSD 在硬件層面做了很多努力,但畢竟還是有限。 btrfs 用戶可以使用 mount 參數打開對 SSD 的特殊優化處理。btrfs 用戶可以使用 mount 參數打開對 SSD 的特殊優化處理。
  • 數據一致性相關的特性

    • COW 事務
      • 所謂 COW,即每次寫磁盤數據時,先將更新數據寫入一個新的 block,當新數據寫入成功之后,再更新相關的數據結構指向新 block 。
      • COW 只能保證單一數據更新的原子性。但文件系統中很多操作需要更新多個不同的元數據,比如創建文件需要修改以下這些元數據。任何一個步驟出錯,文件便不能創建成功,因此可以定義為一個事務。
    • Checksum
      • 由于硬件原因,從磁盤上讀出的數據會出錯。比如 block A 中存放的數據為 0x55,但讀取出來的數據變是 0x54,因為讀取操作并未報錯,所以這種錯誤不能被上層軟件所察覺。
      • 解決這個問題的方法是保存數據的校驗和,在讀取數據后檢查校驗和。如果不符合,便知道數據出現了錯誤。
      • Btrfs 采用單獨的 checksum Tree 來管理數據塊的校驗和,把 checksum 和 checksum 所保護的數據塊分離開,從而提供了更嚴格的保護。
  • 多設備管理相關的特性

    • 多設備管理
      • Btrfs 支持動態添加設備。用戶在系統中增加新的磁盤之后,可以使用 btrfs 的命令將該設備添加到文件系統中。
      • 為了靈活利用設備空間,Btrfs 將磁盤空間劃分為多個 chunk 。每個 chunk 可以使用不同的磁盤空間分配策略。
    • Subvolume
      • Subvolume 是很優雅的一個概念。即把文件系統的一部分配置為一個完整的子文件系統,稱之為 subvolume 。
      • 這種模型有很多優點,比如可以充分利用 disk 的帶寬,可以簡化磁盤空間的管理等。
      • Subvolume 可以作為根目錄掛載到任意 mount 點。 subvolume 是非常有趣的一個特性,有很多應用。
    • 快照和克隆
      • 快照是對文件系統某一時刻的完全備份。建立快照之后,對文件系統的修改不會影響快照中的內容。這是非常有用的一種技術。
      • 快照一般是只讀的,當系統支持可寫快照,那么這種可寫快照便被稱為克隆。克隆技術也有很多應用。比如在一個系統中安裝好基本的軟件,然后為不同的用戶做不同的克隆,每個用戶使用自己的克隆而不會影響其他用戶的磁盤空間。非常類似于虛擬機。
    • 軟件 RAID
      • Btrfs 很好的支持了軟件 RAID,RAID 種類包括 RAID0,RAID1 和 RAID10。
      • Btrfs 缺省情況下對 metadata 進行 RAID1 保護。
  • 其他特性

    • Delay allocation
    • Inline file
    • 目錄索引 Directory index
    • 預分配

Note: 點擊這里,查看參考文章

1.4 擴展查看

# 查看系統支持的文件系統
`cat /proc/filesystems`

# 查看操作系統中安裝的模塊
`lsmod`

2. 文件系統剖析

我們知道不同的操作系統所使用的文件系統是不一樣的。舉例來說,Windows 98 以前所使用的是文件系統是 FAT,Windows 2000 以后的版本有所謂的 NTFS 文件系統。至于 Linux 的正規文件系統則為 Ext2(Linux second extended file system,Ext2fs)。之后又出現了改進版的 Ext3 和 Ext4 ,總體上變化不大。

2.1 文件系統的對比

2.1.1 Linux的 Ext2 文件系統

Linux的 Ext2 文件系統

假設一個文件的屬性和權限信息是存放在 3 號的 inode 上,而文件的實際數據是存放在 1、4、6、11 這四個 block 中,那么當操作系統要訪問該文件時,就能據此來排列磁盤的閱讀順序,可以掃描一次就將 4 個 block 內容讀出來。這種訪問方式稱為索引式文件系統(indexed allocation)。而且 ext 在每兩個文件之間都留有相當巨大的空閑空間。當文件被修改、體積增加時,它們通常有足夠的空間來擴展。因此在一定程度上保證了 block 的訪問范圍不會跨度很大,減小了磁頭的移動距離。

2.1.2 Windows的 FAT32 的文件系統

Windows的 `FAT32` 的文件系統

在往 FAT 文件系統中存入一個文件時,系統會盡量存放在靠近磁盤開始的地方。當你存入第二個文件時,它會緊挨著第一個文件。當進行頻繁的刪除修改后,block 就會分散的特別厲害。FAT 文件系統沒有 inode 的存在,所以不能一下子將文件的所有 block 在一開始就讀取出來。每個 block 號碼都記錄在前一個 block 當中,形成一個 block 鏈。當我們需要讀取文件的時候,就必須一個一個地將 block 讀出,例如上圖的讀出順序為 1、6、3、12 。這就會導致磁頭無法在磁盤轉一圈就獲得所有數據,有時候需要來回轉好幾圈才能讀取到這個文件,導致文件讀取性能極差。這就是 Windows 經常需要碎片整理的原因——使離散的數據匯合在一起

2.1.3 Windows系統為什么需要磁盤碎片整理?

相信我們看了上面的內容,一定理解了這個原因是怎么導致的。及時Windows之后開發了NTFS 文件系統。NTFS 文件系統雖然智能了一點,在文件周圍分配了一些“緩沖”的空間,但經過一段時間的使用后, NTFS 文件系統還是會形成碎片。由于 ext 是索引式文件系統,所以基本上不太需要經常進行磁盤碎片整理。

2.1.4 知識擴展

以下是我花了幾張圖,來加深你對于文件系統的理解。

非日志型文件系統
日志型文件系統
虛擬文件系統
文件存儲方式

3. 創建文件系統

3.1 mkfs命令

命令格式:
mkfs [options] [-t type] [fs-options] device [size]

參數選項:

  • -V
    詳細顯示模式
  • -t
    給定檔案系統的型式,Linux 的預設值為 ext2
  • -c
    在制做檔案系統前,檢查該partition 是否有壞軌
  • -l bad_blocks_file
    將有壞軌的block資料加到 bad_blocks_file 里面
  • block
    給定 block 的大小
  • -L
    建立lable

Note:

  • 在使用 mkfs 的時候,在命令行中輸入mkfs之后輸入.tab鍵來查看支持的分區類型。
  • device 預備檢查的硬盤 partition,例如:/dev/sda1,必選。
  • mkfs本身并不執行建立文件系統的工作,而是去調用相關的程序來執行。例如,若在-t參數中指定ext2,則mkfs會調用mke2fs來建立文件系統。使用時如省略指定【塊數】參數,mkfs會自動設置適當的塊數。

3.2 mke2fs命令

ext系列文件系統專用管理工具

命令格式:
mke2fs -O journal_dev [ -b block-size ] [ -L volume-label ] [ -n ] [ -q ] [ -v ] external-journal [ fs-size ]

參數選項:

必要參數

  • <設備名稱> 與設備對應文件,例如/dev/hd1
  • -b<塊大小> 指定塊大小
  • -c 在創建文件系統之前檢查指定的設備
  • -g<塊組數量> 指定一個塊組中塊的數量

選擇參數

  • -t {ext2|ext3|ext4}
  • -b {1024|2048|4096}
  • -N #
    為數據空間創建個多少個inode
  • -m #
    為管理人員預留的空間占據的百分比
  • -O FEATURE[,...]
    啟用指定特性
  • -O ^FEATURE
    關閉指定特性
  • -E<擴展參數>
    為要創建的文件系統指定一些參數
  • -f<不連續區段大小>
    不知道連續區段的大小
  • -F
    強制執行,即使指定設備沒有被掛載或者不是塊設備
  • -l<文件>
    從指定文件中讀取壞的塊列表
  • -i<字節>
    指定每個inode的字節數
  • -j
    創建使用ext3卷號的文件系統
  • -J<擴展參數>
    為使用ext3卷號的文件系統指定一些參數
  • -L
    設置創建的文件系統的標簽
  • -q
    執行時不顯示任何信息
  • -V
    顯示版本信息

3.3 mkswap命令

添加擴展的swap分區

命令格式:
mkswap [options] device [size]

參數選項:

  • -c
    建立交換區前,先檢查是否有損壞的區塊。
  • -p<頁大小>
    使用指定的頁大小
  • -L<標簽>
    指定一個標簽,伺候的 sawpon 可以使用這個標簽

實戰演示:

[root@linux ~]# dd if=/dev/zero of=/extra-swap bs=1024 count=1024   #創建交換分區文件
[root@linux ~]# mkswap /extra-swap 1024     #格式化交換分區
[root@linux ~]# swapon /extra-swap          #加載交換分區

Note:

  • 調整其分區的ID為82
  • [交換區大小] 指定交換區的大小,單位為1024字節

3.4 blkid命令

塊設備屬性信息查看

命令格式:
blkid [OPTION]... [DEVICE]

參數選項:

  • -o<標簽>
    指定輸出格式 (full、value、list\device\udev)
  • -s<標簽>
    顯示指定標簽信息 (LABEL、UUID、TYPE)
  • -U UUID
    根據指定的UUID來查找對應的設備
  • -L LABEL
    根據指定的LABEL來查找對應的設備

實戰演示:

[root@localhost ~]# blkid -s UUID /dev/sda5    #顯示指定設備 UUID
/dev/sda5: UUID="cad7349a-601d-4df4-a46b-90e1ffc29b1b" 

[root@localhost ~]# blkid -s UUID              #顯示所有設備 UUID
/dev/sda5: UUID="cad7349a-601d-4df4-a46b-90e1ffc29b1b" 
/dev/sda1: UUID="d7899bc2-b08e-48cd-b904-54956c085951" 

[root@localhost ~]# blkid -s LABEL /dev/sda5   #顯示指定設備 LABEL
/dev/sda5: LABEL="Disk E"

[root@localhost ~]# blkid -s LABEL             #顯示所有設備 LABEL
/dev/sda1: LABEL="M-fM-^VM-0M-eM-^JM- M-eM-^MM-7" 
/dev/sda5: LABEL="Disk E" 

[root@localhost ~]# blkid -s TYPE              #顯示所有設備文件系統
/dev/sda5: TYPE="swap" 
/dev/sda1: TYPE="ext4" 

[root@localhost ~]# blkid -o device            #顯示所有設備
/dev/sda5
/dev/sda1

[root@localhost ~]# blkid -o list  #以列表方式查看詳細信息
device    fs_type    label    mount point    UUID
---------------------------------------------------------------------------------
/dev/sda5    swap                         cad7349a-601d-4df4-a46b-90e1ffc29b1b
/dev/sda1    ext4               /         d7899bc2-b08e-48cd-b904-54956c085951

3.5 e2label命令

管理ext系列文件系統的LABEL
e2label命令用來設置第二擴展文件系統的卷標。

命令格式:
e2label device [ new-label ]

3.5 tune2fs命令

重新設定ext系列文件系統可調整參數的值

命令格式:
tune2fs [OPTION]... [DEVICE]

參數選項:

  • -l
    查看指定文件系統超級塊信息
  • -c max-mount-counts
    設置強制自檢的掛載次數,如果開啟,每掛載一次mount conut就會加1,超過次數就會強制自檢
  • -i interval-between-checks[d|m|w]
    設置強制自檢的時間間隔[d天m月w周]
  • -m #
    保留塊的百分比
  • -j
    將ext2文件系統轉換為ext3類型的文件系統
  • -L 'LABEL'
    類似e2label的功能,可以修改文件系統的標簽
  • -r reserved-blocks-count
    調整系統保留空間
  • -o [^]mount-option[,...]
    設置或清除默認掛載的文件系統選項
  • -O
    文件系統屬性啟用或禁用
  • -U UUID
    修改UUID號

實戰演示:

# tune2fs -c 30 /dev/hda1           #設置強制檢查前文件系統可以掛載的次數
# tune2fs -c -l /dev/hda1           #關閉強制檢查掛載次數限制。
# tune2fs -i 10 /dev/hda1           #10天后檢查
# tune2fs -i 1d /dev/hda1           #1天后檢查
# tune2fs -i 3w /dev/hda1           #3周后檢查
# tune2fs -i 6m /dev/hda1           #半年后檢查
# tune2fs -i 0 /dev/hda1            #禁用時間檢查
# tune2fs -j /dev/hda1              #添加日志功能,將ext2轉換成ext3文件系統
# tune2fs -r 40000 /dev/hda1        #調整/dev/hda1分區的保留空間為40000個磁盤塊
# tune2fs -o acl,user_xattr /dev/hda1            #設置/dev/hda1掛載選項,啟用Posix Access Control Lists和用戶指定的擴展屬性

3.6 dumpe2fs命令

dumpe2fs命令用于打印“ext”文件系統的超級塊和塊組信息。

命令格式:
dumpe2fs [-bfhixV] [-o superblock=] [-o blocksize=] device

參數選項:

  • -b
    打印文件系統中預留的塊信息
  • -ob<超級塊>
    指定檢查文件系統時使用的超級塊
  • -OB<塊大小>
    檢查文件系統時使用的指定的塊大小
  • -h
    僅顯示超級塊信息
  • -i
    從指定的文件系統映像文件中讀取文件系統信息
  • -x
    以16進制格式打印信息塊成員

實戰演示:

[root@localhost ~]$ sudo dumpe2fs /dev/sda8     #查看sda8磁盤信息
dumpe2fs 1.41.12 (17-May-2010)
Filesystem volume name:   
Last mounted on:          /
Filesystem UUID:          a0794ac7-6cda-4a45-aa45-a97bd32f8c82
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)

3.7 fsck命令

文件系統檢測

命令格式:
fsck [ -sACVRTNP ] [ -t fstype ] [filesys ... ] [--] [ fs-specific-options ] [[ ]]

參數選項:

  • -t FS_TYPE
    檢查那個文件格式的文件系統,類似fsck.FS_TYPE
  • -a
    不提問,自動修復文件系統(請小心使用此選項)。注意 e2fsck(8) 支持 -a 僅僅是為了向前兼容。這個選項被映射到 e2fsck-p 選項,那比較安全一點,不像大多數文件系統檢查器支持的 -a 那樣。
  • -r
    交互式地修復文件系統錯誤(詢問確認)。注意: 如果多個 fsck 在并行執行,這不是一個好想法。還要注意 e2fsck 的默認行為;它也只為了向前兼容才保留這個選項。
  • -R
    當使用 -A 標志來檢查所有文件系統時,跳過root文件系統 (它可能已經被掛載為可讀寫)。
  • -A
    搜索 /etc/fstab 文件,一次檢查所有在文件中有定義的文件系統。這個選項典型地用在 /etc/rc 系統初始化文件中,而不使用多條命令來分別檢查各獨立的分區。

Note:

  • 只輸入fsck命令,版本號
  • FS_TYPE一定要與分區上已經文件類型相同

實戰演示:

[root@localhost ~]# e2fsck -a -y /dev/sda1        #檢查 /dev/sda1 是否有問題,如發現問題便自動修復

3.8 e2fsck命令

ext系列文件專用的檢測修復工具

命令格式:
e2fsck [ -pacnyrdfkvtDFV ] [ -b superblock ] [ -B blocksize ] [ -l|-L bad_blocks_file ] [ -C fd ] [ -j external-journal ] [ -E extended_options ] device

參數選項:

  • -a
    檢查 partition,如發現問題會自動修復
  • -b
    設定 superblock 位置
  • -B size
    指定 size 作為區塊大小
  • -c
    檢查 partition 是否有壞軌
  • -C file
    將檢查結果儲存到 file
  • -d
    輸出 e2fsck debug 結果
  • -f
    e2fsck 預設只會對錯誤的檔案系統檢查,加上 -f 是強制檢查
  • -F
    在檢查前將硬盤的 buffer cache 清空,避免發生錯誤
  • -l list
    記錄了壞軌區塊加入 list 中
  • -d
    打印 e2fsck 的 debug 結果
  • -f
    強制檢查
  • -n
    以 (read-only) 開啟檔案系統
  • -p
    關閉互動模式,如有問題自動修復,等同 -a
  • -v
    顯示詳細報告
  • -y
    啟用使用者互動模式

實戰演示:

[root@localhost ~]# e2fsck -a -y /dev/sda1        #檢查 /dev/sda1 是否有問題,如發現問題便自動修復
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 一個基本的計算機系統由“硬件”和“軟件”組成,一臺Linux設備,主要的組成如下圖所示: 一般情況下,我們所說的L...
    時待吾閱讀 1,673評論 0 16
  • fdisk, partx, kpartx, mke2fs, tune2fs, dumpe2fs, e2label,...
    魏鎮坪閱讀 1,652評論 0 4
  • 轉載自:http://blog.csdn.net/hguisu/article/details/6122513原作...
    miaoiao閱讀 1,543評論 0 7
  • 是的,鳳姐又火了,但是她這次的火與以往不同。 聽說鳳姐開公號了,才開了7天,后臺粉絲已經突破了7萬,我特意搜了她的...
    愚小佳閱讀 347評論 0 0
  • 在學習FFmpeg之前,查閱了很多資料包括官方的、國外的、國內的,相信還是雷霄驊資料最適合初學者,在這里哀悼下大神...
    風與鸞閱讀 1,470評論 2 8