💻 Programming — 2026年4月
2026-04-07 c pracetice tags:[c]
1. Bitwise Operation (位元運算)
考點分析: SSD Tool 需要頻繁組裝 NVMe Command 或操作硬體 Register。位元運算是絕對的必考題。 常見題目: 請寫出 Macro (巨集) 來 Set (設為1)、Clear (設為0) 以及 Toggle (反轉) 變數 a 的第 n 個 bit。
解答:
#define SET_BIT(a, n) ((a) |= (1 << (n)))
#define CLEAR_BIT(a, n) ((a) &= ~(1 << (n)))
#define TOGGLE_BIT(a, n) ((a) ^= (1 << (n)))
#define CHECK_BIT(a, n) (!!((a) & (1 << (n)))) // 判斷第 n 個 bit 是否為 1
在組裝 NVMe 64 bytes Submission Queue Entry (SQE) 時,經常需要精準操作特定 bit (例如 FUA bit 或 PRP offset),熟練 Bitwise 是開發 Validation Tool 的基本功。
2. Struct Memory Alignment (結構體記憶體對齊)
考點分析: 當上層 Python 透過 ctypes 呼叫底層 C DLL 時,如果兩邊的記憶體對齊 (Padding) 不一致,傳遞的資料結構就會錯位,導致 Segmentation Fault 或硬體拒絕指令。 常見題目: 請問以下 Struct 的 size 是多少?為什麼?如何讓它變成緊密排列 (Packed)?
struct TestStruct {
char a;
int b;
char c;
};
答:Size 在 32/64 bit 系統中通常是 12 bytes (而非 6 bytes)。因為編譯器為了 CPU 讀取效率,會進行 Data Structure Padding (對齊 4 bytes)。
解法 (如何變為 6 bytes):使用 #pragma pack 指令。
#pragma pack(push, 1) // 強制 1 byte 對齊
struct TestStruct {
char a;
int b;
char c;
};
#pragma pack(pop) // 恢復預設對齊
3. Pointer & Memory Management (指標與記憶體管理)
考點分析: 測試軟體常需要配置大區塊的記憶體來模擬 Host 端的 Data Buffer,用來驗證 SSD 的讀寫資料正確性 (Data Comparison)。 常見題目: 指標的加減運算,以及 malloc 後沒有 free 會怎樣?
問:
int *ptr = (int *)malloc(10 * sizeof(int));
ptr++; // ptr 移動了多少 bytes?
解答:ptr 會移動 4 bytes (假設 int 是 4 bytes)。指標的加減是基於其指向的型態大小。
4. volatile 關鍵字的應用
考點分析: 面試官想確認你懂不懂「軟體與硬體交界處」的行為。 常見題目: 什麼是 volatile?在什麼情況下必須使用?
- 答 volatile 告訴編譯器該變數的值可能隨時會被外部因素(例如硬體狀態改變、中斷服務常式 ISR、多執行緒)改變,因此強迫編譯器每次都必須重新從記憶體讀取該變數,絕對不能使用 CPU Cache 中的舊值,也不能把這段看似多餘的讀取程式碼最佳化(Optimize)掉。
應用場景: 讀取 SSD Controller 的 Hardware Register 狀態,或是 Polling NVMe Completion Queue (CQ) Doorbell 的值。
架構視野展現 (MP Tool 開發模式)
graph TD
subgraph Host Application
A[Python / C# UI] -->|ctypes / PInvoke| B(C/C++ DLL Dynamic Library)
end
subgraph Middle Layer
B -->|Struct Parsing & Bitwise| C[NVMe Command Construction]
C -->|DeviceIoControl| D[Windows NVMe Driver / JMicron Vendor Driver]
end
subgraph Hardware Layer
D -->|PCIe / USB| E[(JMicron Bridge Controller / SSD)]
end
2026-04-07 PySerial 實戰:UART 通訊與 Deadlock tags:[python]
PySerial 核心觀念與高頻踩坑點 pyserial 本身是執行緒安全 (Thread-safe) 的,意味著你可以從不同的 Thread 同時呼叫 read/write。但「模組安全不代表你的系統設計安全」。Deadlock 通常發生在 I/O 阻塞 (Blocking) 與不當的鎖 (Lock) 競爭。
1. 致命傷:無 Timeout 的 Blocking I/O
import serial
ser = serial.Serial('/dev/tty.usbserial', 115200) # 在 Mac M1 上通常長這樣
data = ser.readline() # 🚨 致命錯誤:如果硬體死機不吐 Log,這行會永久卡死
防禦解法:設定嚴格的 Timeout 機制 永遠不要相信硬體。必須設定 timeout (Read) 與 write_timeout (Write)。
ser = serial.Serial(
port='/dev/tty.usbserial',
baudrate=115200,
timeout=1.0, # 讀取超時 (秒),時間到就算沒資料也會 return
write_timeout=1.0 # 寫入超時,防禦硬體 Flow Control (CTS/RTS) 卡死
)
2. 如何徹底避免 Deadlock?
Deadlock 的經典場景:Main Thread 等待 Worker Thread 結束 (join),但 Worker Thread 因為硬體沒回應卡在 ser.read(),且剛好握著某個 threading.Lock 不放,導致全域當機。
防禦架構:非阻塞讀取 (Non-blocking) + Queue 解耦 不要讓主程式直接操作 UART,也不要用單一的 Mutex Lock 去包住 I/O 操作。唯一最佳實踐是:開設一個獨立的 Daemon Thread 專職讀取,並利用 queue.Queue 與主程式溝通。
import serial
import threading
import queue
import time
class UartMonitor:
def __init__(self, port, baudrate):
self.ser = serial.Serial(port, baudrate, timeout=0.1)
self.log_queue = queue.Queue(maxsize=1000)
self.running = True
# 啟動背景監聽執行緒 (Daemon=True 確保主程式結束時它會自動關閉)
self.rx_thread = threading.Thread(target=self._read_loop, daemon=True)
self.rx_thread.start()
def _read_loop(self):
while self.running:
try:
# 檢查 Buffer 內是否有資料,避免無謂的 read 阻塞
if self.ser.in_waiting > 0:
raw_data = self.ser.read(self.ser.in_waiting)
# 放入 Queue,若滿了不會卡死 (timeout 防護)
self.log_queue.put(raw_data, timeout=0.1)
else:
time.sleep(0.01) # 讓出 CPU 資源,避免 100% 佔用
except Exception as e:
print(f"UART Error: {e}")
self.running = False
def get_logs(self):
logs = []
while not self.log_queue.empty():
logs.append(self.log_queue.get())
return logs
def close(self):
self.running = False
self.rx_thread.join(timeout=1.0) # 設定 join 的 timeout 避免主執行緒卡死
self.ser.close()
###3. 系統架構
graph TD
subgraph Hardware DUT
A[SSD / Bridge IC] -->|UART TX| B(Serial Port)
end
subgraph Python Tool Architecture
B -->|in_waiting & read| C[Daemon RX Thread]
C -->|Queue.put| D[(Thread-Safe Queue)]
E[Main Thread / UI] -->|Queue.get| D
E -->|Regex Analysis| F[Log Parser / Error Detector]
end
style C fill:#f9f,stroke:#333,stroke-width:2px
style D fill:#bbf,stroke:#333,stroke-width:2px
2026-04-13 Kivy App Layout tags:[python, kivy]
重點
- (說明這次學的內容)
程式碼片段
# 範例
from kivy.app import App
問題與解法
| 問題 | 解法 | |——|——| | | |
📅 範本區塊
## YYYY-MM-DD 主題 tags:[語言, 主題]
重點
- (學習重點)
程式碼片段
// code here
問題與解法
| 問題 | 解法 | |——|——| | | |
參考資料
-