---
# System prepended metadata

title: 2025q1 Homework1 (ideas)
tags: [Linux]

---

# 2025q1 Homework1 (ideas)
contributed by < `liangchingyun` >

## Linux 排程器研究

## 改進 Linux 核心的 lib/list_sort.c

## 裝置驅動程式開發
### Linux 核心專題: [虛擬無線網路裝置驅動程式](https://hackmd.io/@sysprog/rJ-LF4nNC)
[vwifi](https://github.com/sysprog21/vwifi) 是一個具體而微的 WiFi 裝置驅動程式，採用 cfg80211 框架，目前支援掃描、連接等 cfg80211 的介面操作，並得以正確處理 Tx/Rx 封包。

---
#### TODO: 支援 Linux v6.8+
##### scan_width
Problem：
`cfg80211_inform_bss` 中的 `scan_width` 在 v.6.7 以後的版本已被移除，原因是掃描頻寬目前都是以 20MHz 為主，因此不需要另外描述掃描頻寬。

Solution：
確保程式碼中有用到 `scan_width` 的部份只在 v.6.7 前做運用。

##### cfg80211_beacon_data
Problem：
`cfg80211_beacon_data` 在 v.6.7 以後的版本以後被加到 `cfg80211_ap_settings` 中。

Solution:
加入 `cfg80211_ap_update` ，其中包含更動的兩個參數及 `cfg80211_beacon_data` 。 回呼函式中有用到 `cfg80211_beacon_data` 的部份也進行調整。

---
#### TODO: 建立背景知識
1. 《[802.11 Wireless Networks: The Definitive Guide, 2/e](https://www.oreilly.com/library/view/80211-wireless-networks/0596100523/)》
2. 〈[Lightweight and Fast WiFi Access in Virtual Machines](http://osseu2023.sched.com/event/1OGgh)〉, Open Source Summit Europe 2023
---
#### TODO: Emulate rate and mcs
有一些回呼函式還沒有被實作，例如 station dump (顯示與 Wi-Fi AP 連接的 station 的相關資訊，包括資料傳輸率和 MCS )。

Modulation 可以控制資源單位可以攜帶幾個 symbol (bits) ，因此會影響資料傳輸率。
![Screenshot from 2025-03-10 10-40-36](https://hackmd.io/_uploads/HyJ8WRoikg.png)


採用 802.11n (HT) 做為 PHY，設置如下 :
Modulation : 64-QAM
Data Bandwidth : 20MHz
Number of Spatial Streams : 4

參照 802.11n (HT) 調變對照表可得:
Number of Data Subcarriers : 52
Number of Coded Bits per Subcarrier per Stream : 6
Coding : 5/6
OFDM Symbol Duration : 3.2 us
Guard Interval Duration : 0.8 us

代入上方計算資料傳輸率的公式可得 data rate = 260 Mbps ，藉此驗證程式所計算出來的結果是否相符。

---
#### TODO: 實作 vwifi_{set,get}_tx_power

在結構體 `vwifi_vif` 上新增 `tx_power` 以描述裝置的傳輸功率。

在 `cfg80211_ops` 的架構上新增實作 `vwifi_set_tx_power` 及 `vwifi_get_tx_power` 兩個回呼函式，則使用者可以透過 **iw dev [interface] set txpower [auto/limit/fixed] [transmit power (mBm)]** 設定裝置傳輸功率。

Problem:
在使用 `iw` 指令時，會導致 `et_tx_power` 的輸入參數 `wdev` 為 NULL，詳見 [cfg80211: allow per interface TX power setting](https://github.com/torvalds/linux/commit/c8442118ad9cd05cfe3b993f058e70ab25b1009a) 。

Solution:
新增函式 `wiphy_get_vwifi_vif` 改以利用參數 `wiphy` 取得裝置的 virtual interface，而非 `wdev` 。

==改進方向==
加上距離位置設定，就可以推得 station 所收到 Wi-fi AP 的訊號。
![image](https://hackmd.io/_uploads/H1UuuAsoye.png)

---
#### TODO: 實作 Ad-hoc (IBSS) mode
實作輕量化的傳輸行為模式

##### 新增 AD-HOC interface type
當一個裝置被設定為 Ad-hoc mode ，就可以跟其他處在同一個 Ad-hoc 網路的裝置任意傳輸，而不用直接連線。

在 `wiphy` 上新增 `NL80211_IFTYPE_ADHOC` interface type，使 Linux 系統能知道此裝置已成為 Ad-hoc (IBSS) 模式（透過 `vwifi_change_iface` 的 operation 切換）。使用者可透過命令 **iw dev [interface] set type ibss** 將裝置切換成 IBSS 模式。

##### 實作 IBSS join 與 leave 機制

加入、離開特定頻段的 IBSS 網路。

1. 建立結構體來存放資訊。
2. 建立 `ibss_list` 以便快速找到所有的 IBSS 裝置。

##### 實作 AD-HOC 封包傳遞機制
在轉送前要確認 source 和 destination 是否處於相同 IBSS cell，以及確認是否在該 IBSS cell 的同個 BSS 中。

##### Ping Test
測試：
1. 同 IBSS cell 中 ping 特定裝置
    ![image](https://hackmd.io/_uploads/BJEia0jiJl.png)
2. ping 處於不同 IBSS cell 的裝置
    兩者處於不同 IBSS，無法通訊。傳輸裝置會三度嘗試用 ARP Request 請求 mac address，但沒有裝置回應。
3. ping 處於 STA mode 的裝置
    如預期般失敗。

##### 使 IBSS 支援掃描
`ah_inform_bss(vif)`
執行 scan 可發現該 bss 資訊


---

### Linux 核心專題: [虛擬攝影機裝置](https://hackmd.io/@sysprog/HJBxRsRr0)
![image](https://hackmd.io/_uploads/B1t4fenokg.png)
使用 V4l2 框架以及 Linux Frambuffer API
運作流程：將資料寫入虛擬 Frambuffer 中，影片播放程式可以透過 /dev/videoX 來播放影片
![image](https://hackmd.io/_uploads/H1cnvx2s1l.png)

#### V4l2 (Video4Linux version 2)
Linux 下關於視訊設備的驅動框架，支援的設備有：
1. Video capture device (ex. 攝影機)
2. Video output device (ex. 螢幕)
3. Radio device （沒有影像，只有聲音）

兩種角度來看 V4L2 框架
1. userspace 角度
    常見的 ioctl 參數
    * VIDIOC_QUERYCAP: 詢問 V4L2 裝置的 capability
    * VIDIOC_S_INPUT / VIDIOC_G_INPUT: 設置、取得目前的輸入來源
    * VIDIOC_S_FMT / VIDIOC_G_FMT: 設置、取得 V4L2 裝置的 format (ex. resolution)
2. 驅動程式開發者角度
    * 關係綁定
        * 將 V4L2 框架所提供的結構體嵌入到自己所定義的結構體中
        * 透過 V4L2 框架所提供的函式將自定義的結構體跟 V4L2 框架作綁定
    * ioctl 等函數綁定
        * 實作特定函式並且將函式跟 V4L2 框架綁定
        * 當某見事情發生時，驅動框架就會呼叫綁定的程式

#### Linux Frambuffer API
Frambuffer: RAM 中的一段連續記憶體，CPU 或 GPU 會把要顯示的影像放到 Framebuffer 中，讓 Display 裝置顯示。
![image](https://hackmd.io/_uploads/B1zRLghikg.png)
![image](https://hackmd.io/_uploads/SkDSPe2jye.png)

---
#### TODO: 在 Linux v6.8+ 運作
Problem:
在其版本上無法成功編譯

Solution:
1. 修正呼叫函式時所用的參數數量: `class_create(owner, name)` --> `class_create(name)`
2. 修正 `struct vb2_queue` 的 member 名稱: `min_buffers_needed` --> `min_queued_buffers`
3. 修改初始化 `struct fb_info` 的方式: `info->flags = FBINFO_FLAG_DEFAULT;` --> `fb_data->info = framebuffer_alloc(0, &dev->vdev.dev);`
    注意：不可以直接改成定值，以防 Linux 核心哪天將初始值改掉。
---
#### TODO: 修正記憶體操作
Problem:
有多個載入模組時所配置的記憶體位置在卸載時沒有被釋放，導致 memory leak。

Solution:
使用 `rcu_varrier()` 來解決來不及釋放的記憶體問題。

---

### Linux 核心專題: [改進 LKMPG](https://hackmd.io/@sysprog/SJS4uStUA)
LKMPG (Linux Kernel Module Programming Guide)

---
#### TODO: 閱讀 LKMPG 並紀錄問題 (含可改進之處)
Problem:
tasklet 在運作時是 non-blocking 的，因此一定會讓 `tasklet_fn` 全部完成後才會繼續做其他事，且在 tasklet 中不宜使用 delay 或 sleep 等操作。

Solution:
將範例中的 delay 時間做調整。

---

#### TODO: 加上 simrupt 到 LKMPG 來說明 tasklet, mutex, kfifo 等使用方式

##### 使用 [simrupt](https://github.com/sysprog21/simrupt)
simrupt 是一個 Linux 核心模組，用於展示延遲工作 (deferred work) 和以下核心概念實作：
* Circular Buffer (環形緩衝區)：儲存和處理資料流。
* Mutex Lock (互斥鎖)：保護臨界區避免多執行緒競爭。
* IRQ (中斷請求) 和 SoftIRQ (軟中斷)：處理硬體中斷和軟體中斷。
* Tasklet 和 Workqueue (工作佇列)：處理延遲任務。
* Kernel Thread (核心執行緒)：建立並管理核心的背景任務。

##### Tasklet

`tasklet` 是 Linux kernel 中的一中軟中斷機制，用於中斷上下文中處理較長時間的任務，相關的定義及函式都存在 [linux/interrupt.h](https://github.com/torvalds/linux/blame/master/include/linux/interrupt.h) 中。

##### Mutex
process 使用 mutex 時，必須先持有 mutex 才得以進入 CS (critical section) 存取資源，
結束後再釋放 mutex 讓其他 process 使用。

若無使用 mutex 確保 critical section 的單一存取，有可能會發生 [race condition](https://zh.wikipedia.org/zh-tw/%E7%AB%B6%E7%88%AD%E5%8D%B1%E5%AE%B3)。

![Screenshot from 2025-03-11 11-16-49](https://hackmd.io/_uploads/BJCrjQ6oyg.png)

##### kfifo
> [linux/kfifo.h](https://github.com/torvalds/linux/blob/master/include/linux/kfifo.h)
> [linux/kfifo.c](https://github.com/torvalds/linux/blob/master/lib/kfifo.c)

* Linux 核心中的 Ring Buffer 機制。
* 若只有單一讀取端與單一寫入端，二者沒有共享被修改的控制變數的情況下，不需要並行控制。
* 生產者-消費者模式的資料傳遞；中斷上下文與 process 上下文間的資料傳遞。
* 寫滿後自動從開頭覆寫，達到記憶體重複使用，減少記憶體配置與釋放的頻率。


## 記憶體管理
### Linux 核心專題: [rhashtable 及核心記憶體管理研究](https://hackmd.io/@sysprog/rkOByUtI0)
Rhashtable (Relativistic hash tables)

在過去的 hash tables 中，若需要進行同步的存取，會需要 mutex locks 來做存取的控制。但在多核處理器的環境底下， mutex locks 導致使執行序相互等待，效率下降。

* Read-Copy Update (RCU)
    一種同步方法，適用於讀取次數比修改次數多的環境。
    
Problem:
Bucket 數量太少，每個 bucket 後面接的鏈結串列很長，節點讀取很花時間
--> 擴張 hash table 使 bucket 增加
--> 要做 resizing ，影響讀取效率

---
#### TODO: 閱讀 [rhashtable](https://hackmd.io/@linjohn/rhashtable)，紀錄核心記憶體管理相關問題
##### Table shrinking
縮小 hash table，減少 bucket 數量。

> Step 0: 原本的 hash table 有奇數、偶數的 bucket：
![image](https://hackmd.io/_uploads/HksG3H6jJe.png)

> Step 1: 建立新的 hash table 指標，指向目前 hash table 第一個 bucket 的第一個節點：
![image](https://hackmd.io/_uploads/HJYk2S6jyl.png)

> Step 2: 把奇數 bucket 的最後一個節點連接到偶數 bucket 的第一個節點：
![image](https://hackmd.io/_uploads/S1mypBpoJl.png)

> Step 3: 把原始 hash table 的指標刪除
![image](https://hackmd.io/_uploads/Sk09TB6okx.png)
注意：可能還有 readers 在查找資料，因此須等一段時間，確保所有 readers 皆已查找完畢，再進行刪除。

> Step 4: 發布新的 hash table ，確認接下來的 readers 都讀到最新的內容
![image](https://hackmd.io/_uploads/B17MCSps1g.png)


##### Table expansion

> Step 1: 新的 hash table ，奇數 bucket 連接到舊有的奇數節點，偶數 bucket 連接到舊有的偶數節點
![image](https://hackmd.io/_uploads/SkefkUTske.png)

> Step 2: 將舊有的 hash table 指標指向新的 hash table 
![image](https://hackmd.io/_uploads/SJSiy8pi1x.png)

> Step 3: 等 readers 全部讀取完，刪除舊的指標
![image](https://hackmd.io/_uploads/S1mXlITiyl.png)

> Step 4: 做指標的修改 (unzip)，第一個節點會往下尋找在新的 hash table 與它在相同 bucket 中的節點
![image](https://hackmd.io/_uploads/HyV1zI6i1g.png)
![image](https://hackmd.io/_uploads/rkLLM8aoye.png)

> Step 5: 持續上個步驟直到所有節點都指向新的 hash table
![image](https://hackmd.io/_uploads/HJ_FML6i1x.png)


---
#### TODO: 確保 [rhashtable](https://hackmd.io/@linjohn/rhashtable) 對應的程式碼可運作於 Linux v6.8

比較 RP, DDDS, rwlock 在兩種情況下效能的差異。
1. No resizing and $2^{13}$ buckets
2. Continuous resizing between $2^{13}$ and $2^{14}$ buckets

在過去的版本的 rhashtable 結構體中，若要插入、刪除或 resize 的操作，需要使用 mutex lock 來保護 hash table ，防止操作被同步。而最新版本的中則使用 per-bucket spinlocks ，只鎖定正在被修改的 bucket 而非整個 hash table ，使其他的 bucket 則可以繼續進行原本的操作。

---

### Linux 核心專題: [高效記憶體配置器](https://hackmd.io/@sysprog/rkZQsLhLR)

## 亂數產生器
###  Linux 核心專題: [亂數產生器研究](https://hackmd.io/@sysprog/BkhlALt8A)