---
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);
}
```