--- tags: linux2022 --- # 2022q1 Homework3 (fibdrv) contributed by < `BensonYang1999` > ## 實作前準備 ### 閱讀 《[The Linux Kernel Module Programming Guide](https://sysprog21.github.io/lkmpg/)》 :::spoiler 依照步驟實作,成功編譯出 hello world ,並成功執行 ```shell $ sudo insmod hello-1.ko $ sudo lsmod | grep hello hello_1 16384 0 $ sudo rmmod hello_1 $ sudo journalctl --since "1 hour ago" | grep kernel 三 08 21:26:27 benson-ubuntu kernel: Hello world 1. 三 08 21:26:45 benson-ubuntu kernel: Goodbye world 1. ``` 產生出 Module Dpcumentation ```shell $ modinfo hello-4.ko filename: hello-4.ko description: A sample driver author: LKMPG license: GPL srcversion: 510C26102AE3F8D731FE755 depends: retpoline: Y name: hello_4 vermagic: 5.13.0-30-generic SMP mod_unload modversions ``` 傳入參數 ```shell $ sudo insmod hello-5.ko mystring="bebop" myintarray=-1 $ sudo dmesg -t | tail -7 myshort is a short integer: 1 myint is an integer: 420 mylong is a long integer: 9999 mystring is a string: bebop myintarray[0] = -1 myintarray[1] = 420 got 1 arguments for myintarray. ``` 待續 ::: ### 前期準備 :::spoiler * linux 核心版本 ```shell $ uname -r 5.13.0-30-generic ``` * 套件安裝 ```shell $ sudo apt install linux-headers-`uname -r` Reading package lists... Done Building dependency tree Reading state information... Done linux-headers-5.13.0-30-generic is already the newest version (5.13.0-30.33~20.04.1). 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. ``` * 檢查使用者 ```shell $ whoami benson $ sudo whoami root ``` * 安裝工具 ```shell $ sudo apt install util-linux strace gnuplot-nox ``` * 取得原始程式碼並測試 ```shell $ git clone git@github.com:BensonYang1999/fibdrv.git $ cd fibdrv $ make check Passed [-] f(93) fail input: 7540113804746346429 expected: 12200160415121876738 $ modinfo fibdrv.ko filename: /fibdrv.ko version: 0.1 description: Fibonacci engine driver author: National Cheng Kung University, Taiwan license: Dual MIT/GPL srcversion: 9A01E3671A116ADA9F2BB0A depends: retpoline: Y name: fibdrv vermagic: 5.13.0-30-generic SMP mod_unload modversions $ sudo insmod fibdrv.ko $ ls -l /dev/fibonacci crw------- 1 root root 505, 0 三 8 23:32 /dev/fibonacci $ cat /sys/class/fibonacci/fibonacci/dev 505:0 $ cat /sys/module/fibdrv/version 0.1 $ lsmod | grep fibdrv fibdrv 16384 0 $ cat /sys/module/fibdrv/refcnt 0 $ sudo rmmod fibdrv ``` 測試內容接符合預期 ::: --- ## Fix C99 variable-length array (VLA) is not allowed in Linux kernel. 這裡原本使用動態宣告陣列儲存斐波那契數列,但是 Linux 核心開發不傾向使用 VLA,因此編譯時會產生警告 ```shell fibdrv.c: In function ‘fib_sequence’: fibdrv.c:30:5: warning: ISO C90 forbids variable length array ‘f’ [-Wvla] 30 | long long f[k + 2]; | ^~~~ ``` 我參考講義中提到的 [Fast Doubling](https://chunminchang.github.io/blog/post/calculating-fibonacci-numbers-by-fast-doubling) 作法,嘗試修改這部份的程式碼 ```c static long long fib_sequence(long long k) { if (k <= 2) return k ? 1 : 0; long long n = 0; if (k % 2) { n = (k - 1) / 2; return fib_sequence(n) * fib_sequence(n) + fib_sequence(n + 1) * fib_sequence(n + 1); } else { n = k / 2; return fib_sequence(n) * (2 * fib_sequence(n + 1) - fib_sequence(n)); } } ``` 修改後的程式雖然還是沒辦法處理 F~93~ 以上的大數,但可以解決編譯時的 VLA 問題 ## 平台轉換 在參考 [laneser](https://hackmd.io/@laneser/fibdrv) 的作業後,發現可以使用 raspberry pi 完成作業,因此我毅然決然決定更換平台,使用 `raspberry pi 3b+` ,以利筆記的書寫 (因為 ubuntu 的中文輸入法不是很好用) 更換平台後的環境 ```shell $ gcc --version gcc (Debian 10.2.1-6) 10.2.1 20210110 $ lscpu Architecture: aarch64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 4 On-line CPU(s) list: 0-3 Thread(s) per core: 1 Core(s) per socket: 4 Socket(s): 1 Vendor ID: ARM Model: 4 Model name: Cortex-A53 Stepping: r0p4 CPU max MHz: 1400.0000 CPU min MHz: 600.0000 BogoMIPS: 38.40 Vulnerability Itlb multihit: Not affected Vulnerability L1tf: Not affected Vulnerability Mds: Not affected Vulnerability Meltdown: Not affected Vulnerability Spec store bypass: Not affected Vulnerability Spectre v1: Mitigation; __user pointer sanitization Vulnerability Spectre v2: Not affected Vulnerability Srbds: Not affected Vulnerability Tsx async abort: Not affected Flags: fp asimd evtstrm crc32 cpuid ``` ## 排除干擾效能分析的因素 ### 抑制程式使用特定核心 在 `/boot/cmdline.txt` 檔案中加入參數 `isolcpus=3` ,重開機之後即可排除程式利用 `core 3` ### 排除干擾效能分析的因素 #### 抑制 address space layout randomization (ASLR) ```shell $ sudo sh -c "echo 0 > /proc/sys/kernel/randomize_va_space" ``` #### 設定 scaling_governor 為 performance 建立檔案 `performance.sh` ,並加入以下內容 ```shell for i in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor do echo performance > ${i} done ``` 之後用 `$ sudo sh performance.sh` 執行 ##時間測量 這部分將參考 [KYG-yaya573142 的報告](https://hackmd.io/@KYWeng/rkGdultSU) ,嘗試修改 `fib_write` ```c static ssize_t fib_write(struct file *file, const char *buf, size_t size, loff_t *offset) { ktime_t kt; kt = ktime_get(); fib_sequence(*offset); kt = ktime_sub(ktime_get(), kt); return (ssize_t) ktime_to_ns(kt); } ``` 結果在執行 `make check` 時,會報錯 ```shell ... -Writing to /dev/fibonacci, returned the sequence 157 +Writing to /dev/fibonacci, returned the sequence 1 ... make: *** [Makefile:40: check] Error 1 ``` 推測是 `fib_write` 的回傳值有問題,因此參考 [laneser](https://hackmd.io/@laneser/fibdrv#%E9%87%8F%E6%B8%AC%E5%9F%B7%E8%A1%8C%E6%99%82%E9%96%93) 的筆記,修改回傳值 ```c static ssize_t fib_write(struct file *file, const char *buf, size_t size, loff_t *offset) { if (buf) return 1; ktime_t kt; kt = ktime_get(); fib_sequence(*offset); kt = ktime_sub(ktime_get(), kt); return (ssize_t) ktime_to_ns(kt); } ```