前言
昨天 [Day 09],我們成功寫出了 20 行的 Bash 腳本,透過 ConfigFS 讓 EdgeNode 搖身一變成為一顆 USB 隨身碟。只要插上 Windows 電腦,醫師就能輕鬆拿到病患的生理訊號資料。
然而,當這套系統真正進入醫療場域時,殘酷的現實才剛開始。
問題情境:當醫生不小心按下了「格式化」...
「這個隨身碟好像有點怪怪的,Windows 跳出提示問我要不要修復,我就按了『格式化』,結果資料全不見了!」 在臨床場域,終端使用者的 IT 背景參差不齊。如果你只是把一個普通的 FAT32 虛擬磁碟 (Backing File) 直接掛載給 Windows 使用,你將面臨以下幾種災難:
誤刪檔案:使用者看完資料後,順手把重要的 .encsv 刪除,導致後續無法上傳到雲端。
植入病毒:隨身碟是病毒最愛的傳播途徑,如果 Windows 是一台中毒的公用電腦,我們的醫療設備可能瞬間淪為毒窟。
格式化浩劫:Windows 有時會誤判未正常退出的 FAT32 系統,並「熱心」地建議使用者格式化。一旦按下確定,我們的 piusb.bin 虛擬磁碟檔案結構將被徹底摧毀。
面對這種情況,傳統的 Linux 檔案權限 (chmod, chown) 完全無用武之地,因為在 USB 協定中,Windows 掌握了對 FAT32 的生殺大權。
錯誤嘗試:依賴使用者的「自律」
工程師一開始的防呆設計,往往是在使用手冊上用紅字寫下:「嚴禁刪除任何檔案,嚴禁格式化本機磁碟!」 或者,在隨身碟裡面放一個名為 DO_NOT_DELETE.txt 的警告檔案。 事實證明,這些做法在忙碌的醫療現場是無效的。我們需要的是系統層級的「物理 (協定) 防禦」。
底層原理:解密 mass_storage 的 LUN 參數
回到我們昨天在 ConfigFS 建立的目錄: /sys/kernel/config/usb_gadget/g1/functions/mass_storage.usb0/lun.0/
在這個目錄中,Linux 核心的 mass_storage 驅動程式提供了一系列強大的開關,這些開關直接控制了 USB 協定層對主機 (Host, 即 Windows) 的行為宣告。我們來看看最重要的三個參數:
ro (Read-Only)
當你對這個檔案寫入 1 (echo 1 > ro) 時,Linux 會在 USB 通訊協定中向 Windows 宣告:「這是一顆有寫入保護 (Write-Protected) 開關的隨身碟,而且開關已經被鎖上了。」 這就像小時候磁碟片上的防寫孔。一旦啟用,Windows 就絕對無法寫入檔案、刪除檔案,更不可能進行格式化。
removable (可卸除式媒體)
這個參數控制了 Windows 要把這個裝置視為「本機硬碟」還是「隨身碟」。 如果設為 1 (echo 1 > removable),Windows 就會知道它隨時可能被拔掉,因此會在系統匣顯示「安全地移除硬體」,並且預設會關閉某些過於激進的寫入快取,這對保護我們的資料非常重要。
cdrom (光碟機模式)
這是終極的防禦手段!如果你設定 echo 1 > cdrom,Windows 根本不會把它當成隨身碟,而是會當成一台 USB 外接光碟機。 這完美解決了所有防寫問題(因為光碟本來就是唯讀的),甚至還能支援 .iso 檔的掛載。不過由於我們的應用場景需要動態寫入新生成的 CSV 檔案,光碟機模式並不完全適合,因此我們將採用 ro + removable 的組合。
最終解決方案:打造堅不可摧的防呆隨身碟
理解了這些參數後,我們來修改昨天的 ConfigFS 腳本。我們只需要在把虛擬磁碟 (piusb.bin) 指定給 file 之前,先將 ro 與 removable 屬性開啟即可。
bash
#!/bin/bash
# ... (前面的 VID/PID 宣告省略) ...
mkdir -p functions/mass_storage.usb0
# 【防呆核心】啟用可移除屬性與唯讀保護
echo 1 > functions/mass_storage.usb0/lun.0/removable
echo 1 > functions/mass_storage.usb0/lun.0/ro
# 綁定實體虛擬磁碟檔案
echo "/opt/gateway/piusb.bin" > functions/mass_storage.usb0/lun.0/file
# 綁定並點火
ln -s functions/mass_storage.usb0 configs/c.1/
ls /sys/class/udc > UDC
動態切換的藝術 (Dynamic Read-Only)
你也許會問:「如果設成了唯讀,那 EdgeNode 自己產生了新的病患資料時,要怎麼寫進去?」
這就是最美妙的地方。ro 參數是針對 USB 協定 (Windows 端) 的限制,並不會限制 Linux 本機端的寫入權限。 只要 Linux 本機將 /opt/gateway/piusb.bin 透過 mount 掛載起來,Linux 端的 Python 程式依然可以自由地寫入 .encsv 檔案。而連接在另一端的 Windows 電腦,只能眼睜睜地看著檔案出現,卻無法修改與刪除。
小結
透過對 ConfigFS 參數的深入理解,我們兵不血刃地解決了醫療現場最大的「人為操作災難」。我們沒有寫任何複雜的權限控制邏輯,只是向 Windows 宣告:「我很脆弱,請只讀我」。
但是,雖然隨身碟已經完成,我們的 EdgeNode 卻還要透過另一條 UART 傳輸線來進行韌體更新與控制,這樣線材實在太多了。 明天 [Day 11 - 把序列埠 (CDC ACM) 也塞進同一條 USB 線],我們將施展 ConfigFS 最強大的魔法:複合式設備 (Composite Device),讓隨身碟與序列埠共用同一條 USB 線!