---
# System prepended metadata

title: 硬體 - 設備管理
tags: [Linux Shell]

---

---
title: '硬體 - 設備管理'
disqus: kyleAlien
---

硬體 - 設備管理
===

## Overview of Content

電腦的基礎就是硬體設備（硬碟、記憶體、CPU... 等等），而 Linux 對於硬體的呈現方式也有一定的規則，這個章節就是要說明 Linux 如何管理硬體設備

:::success
* 如果喜歡讀更好看一點的網頁版本，可以到我新做的網站 [**DevTech Ascendancy Hub**](https://devtechascendancy.com/)
    
    本篇文章對應的是 [**理解 Unix/Linux 設備偵測、建立 | 認識與使用 udevd | SCSI 與 Linux 核心**](https://devtechascendancy.com/unix-linux-dev_udevd_scsi/)
:::
[TOC]

## Unix 設備節點概念

Unix 系統中，核心會將 I/O 介面以 **檔案的形式** 型態呈現給使用者看，這些設備有為 **==設備節點==**

> 開發者可以使用 `cat`、`less`、`vim`、重新導向... 等等命令來存取設備

:::info
但請注意，**並非** 所有的設備節點都可以使用 I/O 的方式來存取
:::

### 設備取名規範

* Linux 如 Unix 一樣，會將硬體設備當作檔案，**儲存在 `/dev` 目錄下**，而這個 `/dev` 目錄是提供 **使用者程序** 使用的，使用者程序可以對做讀寫
    
    > 就像是直接對裝置存取一樣

    以下使用 `ls` 查看 `/dev` 目錄
    
    ```shell=
    # 顯示前 30 筆
    
    ls -laF /dev | head -n 30
    ```
    
    並且這些設備顯示有一個簡易的符號可以讓我們快速了解（顯示的最前方）
    
    | 檔案類型 | 符號 | 概述 |
    | -------- | -------- | - |
    | 區塊設備 | b | 固定的區塊大小 |
    | 字元設備 | c | 沒有固定容量（核心不會對字元設備 備份、驗證） |
    | 管道設備 | p | 與字元類似，**不過輸入的數據不一定從核心而來** |
    | Socket 設備 | c | 跨進程、遠端常用到 |
    
    > ![](https://hackmd.io/_uploads/ry4gDI4vn.png)

    :::success
    * **設備編號** 是甚麽？
        
        編號有分為，**主編號、副編號**；相同類型的設備會有相同的主編號（副編號則沒有硬性規定）
    :::
    
    :::warning
    * **所有設備都有對應的檔案**？
        
        NO~ 像是網路介面就沒有設備檔案
    :::

### Linux 改造 `/dev` 目錄：sysfs 介面

* 傳統的 Unix `/dev` 目錄會將所有（使用者程序、核心程序）的設備檔案放至此，沒有詳細分類，而這會造成一個問題…
    
    **Unix 系統每次開機後，同樣設備儲存在 `/dev` 資料夾內的裝置名稱也會不同**
    
    > `/dev` 目錄中的裝置名稱通常是由系統動態生成的，並且可能根據裝置的探測順序或其他因素而變化
    
* 為此 Linux 核心透過一個檔案目錄系統提供 sysfs 介面，它是 **基於硬體性** 統一顯示設備的相關資訊，這就讓 **每次開機時，同樣設備都會顯示與上次相同的資料**
    
    > sysfs 提供的是系統裝置（devices）的相關資訊，而不僅僅是硬體性質；它包括有關系統組件、裝置、驅動程式和其他資源的詳細信息
    
    **sysfs 提供的目錄為 `/sys/devices`**，sysfs 介面會以 `/sys/devices` 下的路徑「作為硬體根路徑」，並呈現相對資訊，範例如下
    
    ```shell=
    cd /sys/devices
    
    # 標準 PC 搜尋 sd.*
    find . -name sd.*

    # 嵌入式的話就要搜尋 eMMC 裝置
    find . -name mmcblk0*
    ```
    
    從下圖中，我們可以看到主硬碟在 `/sys/devices` 目錄下也有對應的資訊（是個目錄）

    > ![image](https://hackmd.io/_uploads/rJCAYF5-C.png)

    :::info
    * **`/dev` 目錄跟 `/sys/devices` 目錄差在哪** ? 
    
        兩者都可以查看硬體訊息，但是 **差異在這兩者的服務目標不同**

        | `/dev` | `/sys/devices` |
        | - | - |
        | 提供程序使用設備 | 用來 **查找設備資訊、管理設備** |


        1. **查找主、副設備號**：**`/sys/devies` 下查找主、副設備號**

            ```shell=
            # 打印 dev 檔案資訊
            cat ./platform/emmc2bus/fe340000.mmc/mmc_host/mmc0/mmc0:59b4/block/mmcblk0/dev
            ```
            > 從下圖中（最下面那行），我們可以看到當前裝置主硬碟的主設備號為 179、副設備號為 0
            > 
            > ![image](https://hackmd.io/_uploads/BkJeoKqWC.png)

        2. **查找區「塊」設備**：在 `/sys/block` 目錄下的裝置都以連結的方式存在，都會連接到 `../device/virtual/block` 目錄下

            ```shell=
            cd /sys

            ls -laF block/
            ```
            > ![](https://hackmd.io/_uploads/S11uxw4wn.png)
    :::
    

### 查找設備的方法

* Linux 中有多種方法可以查看當前系統所裝配的設備、裝置，常見的方式如下…

    1. **使用 `udevadm` 命令** 查看設備
    
    2. 手動 **去 `/sys` 目錄** 下尋找設備
        
        ```shell=
        ls -laF /sys/
        ```
        
        > ![](https://hackmd.io/_uploads/HkiZIjUPn.png)

    2. 查看系統日誌，**使用 `demsg` 命令** 輸出核心日誌

    3. **使用 `mount` 命令** 查看當前已掛載的設備
        
        ```shell=
        mount
        ```
        
        > ![](https://hackmd.io/_uploads/rkHSIi8D2.png)

    4. **查看 `/proc/devices` 文本**：該文本內容顯示系統 ++已經配置驅動++ 的 **字元、區塊** 設備

        ```shell=
        cat /proc/devices
        ```
        > ![](https://hackmd.io/_uploads/HkjiUi8Pn.png)


## 認識 udev & udevd

| 關鍵字 | 簡介 | 補充 |
| -------- | -------- | -------- |
| udev(`Userspace Device`) | Linux 設備管理工具，負責動態管理、識別設備，在找到設備後，自動加入 `/dev` 目錄下 | `udev` 會與內核中的 `sysfs`, `devtmpfs` 交互獲取設備訊息 |
| udevd | 在背景守護 `udev` 進程，有（硬體）事件發生時會先通知 `udevd` 處理，再將處理結果傳遞給 `dev` | 通過監視 `sysfs`, `uevent` 介面來獲取事件通知 |


:::warning
* **udevd 注意事項**：
    
    `udevd` 作為守護進程，系統啟動前期就需要設備檔案，也就是說 `udevd` 應該儘早的啟動
        
    > 並且 **`udevd` 不能依賴任何設備來建立設備檔**
:::

### 內核的 devtmpfs 檔案系統：通知 udevd

* **內核中的 `devtmpfs` 檔案系統 類似於舊的 `devfs` 系統，但它更加簡單**

    `devtmpfs` 是一種臨時的虛擬檔案系統，用於在 Linux 內核中管理和展示裝置（device）

* **`devtmpfs` 發現設備後，處理順序如下**

    1. **`devtmpfs` 在發現新設時通知 `udevd`**

        > 當 Linux 內核發現新的裝置時，devtmpfs 會通知 udevd 進行後續處理
        
    2. `udevd` 在收到消息後，它不會直接建立裝置檔案（device file），而是進行初始化和後續處理
    
    3. 接著 `udevd` 會在 `/dev` 中建立符號連結（`ln`）
    
        ```shell=
        # 可在 `/dev/disk/by-id` 發現 `udevd` 建立的連結
        
        ls -laF /dev/disk/by-id
        ```
        
        :::info
        * udevd 會使用介面類型名稱、廠商、型號、序列號、分區… 等等的組合方式來為符號連結命名 
        :::
        
        > ![](https://hackmd.io/_uploads/HJX2joSw3.png)

### udevd 操作、設定：uevent 事件

* 這個小節來看 `udevd` 的工作：它作為守護進程，當有一個新硬體後，會執行以下操作（上至下，按照順序來看）

    1. 核心透過內部網路 **向 `udevd` 發送 `uevent` 事件**，以下我們來看看當前裝置的主硬碟（`mmcblk0`）收到的 uevent 事件
        
        事件會紀錄在，`/sys/`目錄下硬體的對應資料夾中的

        ```shell=
        cat ./platform/emmc2bus/fe340000.mmc/mmc_host/mmc0/mmc0:59b4/block/mmcblk0/uevent
        ```
        > ![image](https://hackmd.io/_uploads/r1N13K5Z0.png)
        

        :::info
        * 以下是一段簡單的 shell，用來判斷 `/sys/devices/` 目錄下的 `uevent` 檔案

            ```shell=
            #!/bin/bash

            list=$(find /sys/devices/ -name "uevent")

            IFS=$'\n'

            for tmp in $list; do

                #echo "file:$tmp"
                if [ -n "$(cat $tmp)" ] ; then
                    echo "The file=($tmp) has content."
                    cat $tmp
                fi

            done
            ```
        :::

    2. **`udevd` 讀取 `uevent` 中所有屬性資訊**
        
        以下我們來看看更多 uevent 的中可能會紀錄的屬性訊息

        ```shell=
        # `udevd` 收到的事件內容
        # 透過以下屬性，可以獲取 `sysfs` 的設備路徑... 等等訊息

        ACTION=change
        DEVNAME=sde
        DEVPATH=/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host4/target4:0:0/4:0:0:3/block/sde
        DEVTYPE=disk
        DISK_MEDIA_CHANGE=1
        MAJOR=8
        MINOR=64
        SEQNUM=2752
        SUBSYSTEM=block
        UDEV_LOG=3
        ```
    
    3. `udevd` **透過 ++規則++ 解析來決定執行哪些操作**，**`udevd` 的事件規則**：
    
        `udevd` 解析這些事件則是 **透過規則**，這些 **規則可能放置在 ^1.^ `/lib/udev/rules.d`、^2.^ `/etc/udev/rules.d` 目錄下**

        :::success
        * 如果有重名的規則，那則以 `/etc/udev/rules.d` 目錄下的規則為準

        * 規則有相當多，詳細規則內容則可以看 `man 7 udev` 
        :::

        以下以 `60-persistent-storage.rules` 規則來說明

        * **`IMPORT` 導入參數**：執行 `ata_id` 命令

            ```shell=
            # 指令
            cat -n /lib/udev/rules.d/60-persistent-storage.rules

            # 輸出部分內容
            # ATA
            KERNEL=="sd*[!0-9]|sr*",     # 配對以 sd* or sr* 開頭的硬體

                # 要求變數 `ID_SERIAL`
                ENV{ID_SERIAL}!="?*", 

                # 子系統為 scsi
                SUBSYSTEMS=="scsi",  

                ATTRS{vendor}=="ATA", 

                # 上述條件都滿足，則執行以下命令
                IMPORT{program}="ata_id --export $devnode"
            ```
            > ![](https://hackmd.io/_uploads/S1los2BPh.png)

            :::info
            * **`ID_SERIAL` 設定值**？

                **`ENV{ID_SERIAL}!="?*"` 是一個條件句**，`?*` 代表的是一個隨機值，加上 `!=` 判斷後最終的意思就是

                如果 `ENV{ID_SERIAL}` 沒有設定（空），則回傳 true 繼續往下執行，否則返回 false 
                > true: 往下執行判斷 或 指令
                >
                > false: 跳過這個規則，往下執行其他規則
            :::

            其中 `IMPORT{program}="ata_id --export $devnode"` 最終執行的是一個 **`ata_id` 命令**；透過這個命令可以將 rules 過濾完的數據結果寫入到檔案中

            ```shell=
            sudo /lib/udev/ata_id --export /dev/sda
            ```

        * **`SYMLINK` ==建立符號連結==**：建立設備符號連結的命名規則也可以在這裡找到，如下可以看出，它命名的規範

            ```shell=
            # 指令
            cat -n /lib/udev/rules.d/60-persistent-storage.rules

            # 輸出部分內容
            #  sd* / sr* / cciss* 設備使用以下規則
            KERNEL=="sd*|sr*|cciss*", 

                # 類行為 disk
                ENV{DEVTYPE}=="disk", 

                # 並且沒有 Serial id
                ENV{ID_SERIAL}=="?*",

                # 執行以下指令
                SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}"
            ```
            在這裡可以看到 `ENV{ID_SERIAL}=="?*"` 規則的改變！變成如果有設定 `ID_SERIAL` 則往下執行，也就是執行 `SYMLINK` 指令

            ```shell=
            # 執行以下指令，建立 ln 連結

            SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}"
            ```

## udevadm 命令：管理 udevd

udevadm 是管理 `udevd` 的一個強大工具，主要用來搜尋、瀏覽、監控 **`udevd`**

### 查看 udevd 訊息

* 透過 `udevadm` 瀏覽 **`udevd` 從核心接收到的訊息**

    ```shell=
    udevadm info --query=all --name=/dev/sda
    ```
    
    其中首符號代表的意義如下表
    
    | 首符號 | 說明 |
    | - | - |
    | `P` | 代表 `sysfs` 放置的路徑 (`/sys/` 目錄下) |  
    | `N` | 設備節點 `/dev` 目錄下的設備名 |
    | `S` | 設備符號連結 |
    | `E` | **從 ++udev 規則++ 中獲得的額外資訊** |

    > ![](https://hackmd.io/_uploads/r1NT1jLvh.png)


### udevadm 監控設備

* 透過 `udevadm` 監控設備：以下監控所有的訊息

    ```shell=
    udevadm monitor
    ```
    
    > ![](https://hackmd.io/_uploads/Sk1sZsLPn.png)

    命令 `udevadm monitor` 還有其他 Option 可以過濾所需訊息
    
    > 詳細訊息設定可以查看 `man 8 udevadm`
    
    | `udevadm monitor` Option | 功能 |
    | -------- | -------- |
    | `--kernal` | 只查看從 Kernel 獲取的訊息 |
    | `--udev` | 只查看 udev 發送的訊息 |
    | `--property` | 只查看設備屬性 |



### udevadm 命令：查找設備

* Udev manager tool 可以使用 udevadm 指令查看路徑 & 其他屬性
    
    ```shell=
    # 查找所有 name 為 /dev/sda 的設備

    udevadm info --query=all --name=/dev/sda
    ```
    > ![](https://i.imgur.com/QmWQJYx.png)


## SCSI 與 Linux 核心

介紹 Linux 核心對於 SCSI 的支援方式（以下偏理論）


### 認識、理解 SCSI 

* 傳統的 SCSI 硬體設定：由兩個大元素組成，透過 **^1.^ ++SCSI 匯流排++ 連接到 ^2.^++主機配接器++**；其種其種每個設備都會有 `SCSI ID` （主機 Adapter, 設備）

    > SCSI 匯流排: 可能會有 8~16 不等的 `SCSI ID`；匯流排中會有 硬碟、USB、光碟機... 等等硬體

    而電腦並不直接與每個設備通訊，電腦只與「**SCSI 主機 Adapter**」通訊，而 **通訊的語言則是透過 SCSI 命令集**

    > ![](https://hackmd.io/_uploads/HJtzooLw3.png)

    :::warning
    * 新版的的 SAS (`Serial Attach SCSI`) 效能更加出色～
    :::

    :::info
    * **設備都是 SCSI 裝置**？
    
        而現在並沒有很多的 SCSI 設備，但是卻有很多使用 SCSI 指令集通訊的設備（模擬 SCSI 設備），像是 USB, CD, DVD ... 等等
    
    * **STAT 設備也可以是 SCSI 設備**
        
        透過轉換機制（使用 `libata` 庫），對上層表示為 SCSI 裝置（像是 USB 就可作為 SCSI 設備）
        
        :::success
        * 而高效能的 **RAID 控制器，使用硬體來實現 SCSI 轉換**
        :::
    :::

* **我們再重新檢視一次 `lsscsi` 命令**

    ```shell=
    lsscsi
    ```
    其中括號內代表的意義分別是：`SCSI 主機 Adapter`、`SCSI 匯流排編號`、`設備 SCSI ID`、`LUN 邏輯單元編號`

    > ![](https://hackmd.io/_uploads/rJjYaoIv2.png)


### Linux 核心處理 SCSI

* 按照我們對於 SCSI 的了解後，下圖表示的是從硬體到核心是如何透過 `SCIS 子系統` 處理 SCSI 裝置

    > ![](https://hackmd.io/_uploads/rkGTtn8vh.png)

* 接著我們區塊快來看

    1. **SCSI 子系統**：主要分為 3 層
        
        * **最頂層**：按照類型設備類型做不同處理；sd 驅動（或其他驅動） **負責將來自核心區塊設備介面的請求翻譯成 SCSI 協定**

        * **中間層**：調控和分流 SCSI 訊息，負責 **管理系統中所有的 SCSI 匯流排和設備**
        
        * **最下層**：該層中的驅動會向 **特定主機配接器發送 SCSI 協定訊息**，並擷取硬體發送的訊息
            
            > 與頂層的分別：雖然 SCSI 協定對於某類設備是統一的，但不同類型的主機配接器處理 SCSI 的方式不同

            > ![](https://hackmd.io/_uploads/rktD8nLv2.png)

            :::info
            * 通常下層驅動會與頂層驅動一對一配對（eg. `sd` 配對 `ATA Bridge`）
            :::
            
    2. **SCSI & USB 設備**：USB 也有一個子系統，當有 USB 裝置插入時，核心會通知 USB 子系統；與 SCSI 相同分為三層
        
        * **最頂層**：將 USB 協定翻譯成 SCSI 協定（像是一個指令 Map，幫我們做翻譯）
        
        * **中間層**：匯流排管理

        * **最下層**：主機控制驅動
        
            :::info
            * 其種以一個類似 lsscsi 的命令 `lsusb`
                
                ```shell=
                lsusb
                ```
                
                > ![](https://hackmd.io/_uploads/rkAeOhIDn.png)

            :::
        
            > ![](https://hackmd.io/_uploads/HJMJv2LPh.png)
    
    3. **SCSI & ATA 設備**：與 USB 驅動相同，需要一個 **橋接驅動將 STAT 驅動連接到 SCSI 子系統**

        而這裡 **透過 `libata` 庫來達到 ATA 裝置對 SCSI 協定的翻譯工作**
        > 不然會很複雜，因為 SATA, CD/DVD 的 通訊都不同
        
        > ![](https://hackmd.io/_uploads/H1T8t3Uvh.png)

### 通用設備

* 使用者空間（User space）通常是與 SCSI 子系統的最頂層 (各種區塊驅動) 來通訊，所以大多數時間是不需了解 SCSI 通訊協議

* **通用設備**：然而我們也可以繞過 核心提供給使用者的區塊驅動，可以直接與 SCSI 設備交互

    這種交互的管道就是 **通用設備**；可以透過以下指令查看 SCSI 設備對應的通用設備

    ```shell=
    lsscsi -g
    ```

    > ![](https://hackmd.io/_uploads/S1Mxo2LPn.png)

    :::info
    * 通常在考慮到核心複雜度，才會使用到直接操控 **通用設備**
    :::

### 存取設備：`/dev`

* 通常我們使用者空間在存取設備時，**並不是直接讀取驅動，而是透過 ++區塊設備介面++ 來存取**（也就是我們常見的 `/dev` 目錄下的設備文件）

    > ![](https://hackmd.io/_uploads/r1MG2n8D2.png)

## dev 常見設備名

Linux 會依照設備的類型給予一定規則的命名方式 (命名規範)

### 硬碟裝置：`sd*`、`hd*`


* **`sd*`、`hd*` 命名**

    | /dev 中取名 | 說明 |
    | -------- | -------- |
    | `/hd*` | PATA 硬碟，舊版本的 Linux 會將 SATA 辨認為 PATA 設備 |
    | `/sd*` | 大部分是指硬碟，現在大部分 Linux 系統中的硬碟都用 `sd<順序>` 開頭 |

    :::success
    * PATA 設備：
        
        代表舊的區塊設備，這些設備有時候也會被認成 SATA 設備
    
    * **sd 設備：該命名代表的是 ++SCSI dick++**

        小型電腦介面 (`Small Computer System Interface`) 最初是作為設備之間通訊的硬體協定標準 (也就是有一個共同的抽象介面)

        雖然現在已經沒有 `SCSI` 硬體，不過 `SCSI` 的規範介面卻很廣泛 !
        > e.g: Usb 設備就可以實作這個協定
    :::

    
    
* **使用 `lsscsi 指令`**：查看當前設備中所有的 SCSI 裝置，但若是硬碟故障就必須移除，而原來對硬碟的標記也就不一定能使用
    
    ```shell=
    # 安裝套件
    sudo apt install lsscsi
    
    lsscsi
    ```
    
    | 前到後 | 數據 | 說明 |
    | - | - | - |
    | 1 | `[0:0:0:0]` | 設備在系統中的位置 |
    | 2 | `dick` | 設備描述 |
    | 3 | `/dev/sda` | 設備檔案的路徑 |
    
    > ![](https://hackmd.io/_uploads/rkAkPPVvn.png)

### 光碟裝置：`sg*`、`sr*`

* `sr*`、`sg*` 命名：光碟，Linux 會將大部分 **光學儲存設備視為 `SCSI` 設備**，但若是使用舊介面的話，可能被識別為 **PATA 設備**
    
    :::info
    * **光碟可寫不可寫** ?
        
        不可寫設備被取名為 `sr*` (read)，可寫設備會被取名為 `sg*` (generic) 
    :::
    > ![](https://i.imgur.com/qKbPGu6.png)

### 終端設備裝置：`tty/*`、`pts`、`tty`

* `tty/*`、`pts/*`、`tty`：終端設備，這種設備就是典型的非硬體設備，是透過記憶體模擬出來的設備
    
    > 像是 shell 視窗就是偽終端
    
    | 終端設備 | 功能 | 補充 |
    | -------- | -------- | - |
    | tty1 | 第一虛擬控制台 (`X Window`) | - |
    | pts/0 | 第一虛擬終端 (`純文字終端`)，可開 0~7 個 | - |
    | pts | 該目錄中有一個專門的檔案系統 | - |

### 連接埠裝置：`ttyS*`、`lp*`

* 連接埠有分為 ++串列++、++並列++ 連接埠

    | 連接埠 | 功能 | 補充 |
    | -------- | -------- | - |
    | （串）`ttyS*` | 主要在處理 `Baud rate`, `flow control`，像是 Rs-232 | 在 window 上是 `COM*` |
    | （並）`lp*` | 單向並行連接埠設備 | 在 window 上是 `LPT1`、`LPT2` |

    :::info
    * 可插拔 USB 串列 Adapter 和 ACM (`Abstract control module`) 模式下，就是以 **串列連接埠表示**：
        
        其取名是 `/dev/USB*` or `/dev/ACM*`
    :::


### 聲音裝置：`snd*`

* `snd*`、`dsp`、`audio`：聲音設備，Linux 有兩組聲音設備，分別如下
    
    1. `Advanced Linux Sound Architecture` (ALSA) 高級聲音架構：放置在 `/dev/snd`
        
        > ![](https://hackmd.io/_uploads/BkguXjrv2.png)

    2. `Open Sorund System` (OSS) 開放聲音架構：ALSA 可向後支援 OSS

        > eg. 可以將 WAV 檔發送給 `/dev/dsp` 來播放


## 建立設備

設備通常都需要建立一個相對的文件，而這件事通常由 Linux 設備的底層服務自動幫我們完成，但這並不代表我們不能自己建立

### 建立假設備：`dd` 指令

* 在 Linux 中，並非每個設備都是硬體元件，我們可以 **透過記憶體來模擬硬體設備**

* **使用 `dd` 指令**：
    
    該指令可以讀取、寫入到指定檔案 (可以透過 flag 控制直接寫入 or 寫入核心分頁檔案)

    | dd option | 簡述 |
    | -------- | -------- |
    | if=<file\> | 輸入檔案 |
    | of=<file\> | 輸出檔案 |
    | bs=<size\> | 一次讀取、寫入的區塊大小（一起設定） |
    | ibs=<size\> | 輸入的區塊大小 |
    | obs=<size\> | 輸出的區塊大小 |
    | count=<num\> | 複製區塊的總數 |
    | skip=<num\> | 跳過前面多少的區塊，不將他們複製到輸出 |

    ```shell=
    # 讀取 /dev/zero 區塊的資料到當前資料夾中的 testfile 檔案
    # (當前是寫入核心分頁)

    # 一次寫 1024
    # 寫 1K 的數量，最終就是 1M 的大小
    dd if=/dev/zero of=test_file bs=1024 count=1k
    ```
    > ![](https://hackmd.io/_uploads/ryER-wNvn.png)

### 手動建立 dev 設備檔案：`mknod` 指令

* 每個外部硬體裝置通常都會在 `/dev` 目錄下建立自身的目錄
    
    而我們插入硬體裝置後，這工作是通常 **由 `devtmpfs`、`udev` 自動幫我們完成**… 
    
    若要手動建立就要 **使用 `mknod` 指令** （並設定設備主、次號）
    
    > mknod 也說明了，設備在 Linux 中就代表了一個節點

    ```shell=
    # 主設備號 10
    # 副設備號 20
    # 建立塊設備，在 /dev/testFile 目錄下
    sudo mknod /dev/testFile b 10 20

    ls -laF /dev | grep testFile
    ```
    > ![](https://hackmd.io/_uploads/BkEwHsSw3.png)


## Appendix & FAQ

:::info
:::

###### tags: `Linux Shell`
