# 2020q1 Homework2 (fibdrv) contributed by < `unknowntpo` > [TOC] # 大綱 * [2020 年春季 Linux 核心設計課程作業 —— fibdrv](/@sysprog/linux2020-fibdrv) * [fibdrv 作業說明筆記](/XNH6vfe1QUiNQnes_VGIEQ) * [Note: fibdrv code_review](/Q9-sLm0-TvepYw5-5UwRXA) * fibdrv * 費氏數列 * What is q-matrix? * What is the purpose of fast doubling? * [Binary Exponentiation](https://cp-algorithms.com/algebra/binary-exp.html) * 硬體加速 F(n) 的手法 * fast - doubling + clz / ctz 指令 * 應用 * 亂數產生 * fibdrv Linux 核心模組撰寫 * 大數運算 * 使用 struct 來包裝大數字 * 分為 upper, lower, * 型態為 `unsigned long long` * 注意 lower 是否需進位 * Linux VFS 介面 * 使LKM 在 userspace 計算出的 fib bumber 透過 vfs 讓 userspace 的 `client.c` 存取結果 * file_operation * ref: * [你所不知道的 C 語言:物件導向程式設計篇](/@sysprog/c-oop?type=view) * [Linux 核心設計: 檔案系統概念及實作手法](/@sysprog/linux-file-system?type=view) * 核心模式的時間測量 * linux kernel 內的兩種計時功能 * timer * old implementation: jiffies * [Linux 核心設計: 中斷處理和現代架構考量](/@sysprog/linux-interrupt) * new: ktime_t * * timeout - [ ] What's the diff? * client.c 介紹 * why we need copy_to_user? * 效能分析提示 * cpu affinity - [ ] how to check? * `taskset` - [ ] how to improve affinity? * 以特定的 CPU 執行程式 * 限定 CPU 給特定的程式使用 * 排除干擾效能分析的因素 * :panda_face: Linux 核心模組掛載機制 - [ ] 檔案 fibdrv.c 裡頭的 `MODULE_LICENSE`, `MODULE_AUTHOR`, `MODULE_DESCRIPTION`, `MODULE_VERSION` 等巨集做了什麼事,可以讓核心知曉呢? insmod 這命令背後,對應 Linux 核心內部有什麼操作呢? * 利用 `##`合併字串 * ref: * C99/C11 6.4.5 String Literals * [你所不知道的 C 語言:前置處理器應用篇](/@sysprog/c-preprocessor?type=view) * Variable attribute `__attribute__ `的作用是什麼? * insmod 背後的機制 - [ ] 當我們透過 insmod 去載入一個核心模組時,為何 module_init 所設定的函式得以執行呢?Linux 核心做了什麼事呢? - [ ] 試著執行 $ readelf -a fibdrv.ko, 觀察裡頭的資訊和原始程式碼及 modinfo 的關聯,搭配上述提問,解釋像 fibdrv.ko 這樣的 ELF 執行檔案是如何「植入」到 Linux 核心 ## 自我檢查清單 - [ ] 研讀上述 ==Linux 效能分析的提示== 描述,在自己的實體電腦運作 GNU/Linux,做好必要的設定和準備工作 $\to$ 從中也該理解為何不希望在虛擬機器中進行實驗; - [ ] 研讀上述費氏數列相關材料 (包含論文),摘錄關鍵手法,並思考 [clz / ctz](https://en.wikipedia.org/wiki/Find_first_set) 一類的指令對 Fibonacci 數運算的幫助。請列出關鍵程式碼並解說 - [ ] 複習 C 語言 [數值系統](https://hackmd.io/@sysprog/c-numerics) 和 [bitwise operation](https://hackmd.io/@sysprog/c-bitwise),思考 Fibonacci 數快速計算演算法的實作中如何減少乘法運算的成本; - [ ] `lsmod` 的輸出結果有一欄名為 `Used by`,這是 "each module's use count and a list of referring modules",但如何實作出來呢?模組間的相依性和實際使用次數 ([reference counting](https://en.wikipedia.org/wiki/Reference_counting)) 在 Linux 核心如何追蹤呢? - [ ] 注意到 `fibdrv.c` 存在著 `DEFINE_MUTEX`, `mutex_trylock`, `mutex_init`, `mutex_unlock`, `mutex_destroy` 等字樣,什麼場景中會需要呢?撰寫多執行緒的 userspace 程式來測試,觀察 Linux 核心模組若沒用到 mutex,到底會發生什麼問題 ## :penguin: 作業要求 * 回答上述==自我檢查清單==的所有問題,需要附上對應的參考資料和必要的程式碼,以第一手材料 (包含自己設計的實驗) 為佳 :::warning :warning: 如果你在 2020 年 3 月 2 日前,已從 GitHub [sysprog21/fibdrv](https://github.com/sysprog21/fibdrv) 進行 fork,請依據 ==[Alternatives to forking into the same account](https://github.community/t5/Support-Protips/Alternatives-to-forking-into-the-same-account/ba-p/7428)== 一文,對舊的 repository 做對應處置,然後重新 fork ::: * 在 GitHub 上 fork [fibdrv](https://github.com/sysprog21/fibdrv),目標是修正 Fibonacci 數計算的正確性 (現有實作存在缺陷,請指出),隨後改善 `fibdrv` 計算 Fibinacci 數列的執行效率,過程中需要量化執行時間,可在 Linux 核心模組和使用層級去測量 * 原本的程式碼只能列出到 Fibonacci(100) 而且==部分輸出是錯誤的數值==,請修改程式碼,列出後方更多數值 (注意: 檢查正確性和數值系統的使用) * 務必研讀上述 ==Linux 效能分析的提示== 的描述,降低效能分析過程中的干擾; * 在 Linux 核心模組中,可用 ktime 系列的 API; * 在 userspace 可用 [clock_gettime](https://linux.die.net/man/2/clock_gettime) 相關 API; * 分別[用 gnuplot 製圖](https://hackmd.io/@sysprog/Skwp-alOg),分析 Fibonacci 數列在核心計算和傳遞到 userspace 的時間開銷,單位需要用 us 或 ns (自行斟酌) * 嘗試解讀上述實驗的時間分佈,特別是隨著 Fibonacci 數列增長後,對於 Linux 核心的影響。可修改 VFS 函式,允許透過寫入 `/dev/fibonacci` 裝置檔案來變更不同的 Fibonacci 求值的實作程式碼。 ![](https://i.imgur.com/7xyCUVO.png) * 用 printk 固然方便,但其執行時間易受各種因素而不穩定,除了透過統計來觀察,也可改用核心的 sysfs 介面,後者可讓我們自行宣告 show 和 store 介面來提供讀寫操作,可參見 [Sample kobject implementation](https://elixir.bootlin.com/linux/latest/source/samples/kobject/kobject-example.c) (注意: 切換到對應的 Linux 核心版本)。 * 逐步最佳化 Fibonacci 的執行時間,引入[費氏數列分析](https://hackmd.io/@sysprog/fibonacci-number) 提到的策略,並善用 [clz / ffs](https://en.wikipedia.org/wiki/Find_first_set) 一類的指令 (Linux 核心有對應的包裝函式),過程中都要充分量化 # 重現 `Idotrg 同學` 實驗結果 ## 遇到問題 ```shell $ sudo ./bpf_scripts.sh Data will preserved in performance.csv... Press Ctrl+C to stop. sh: 1: objdump: not found Failed to compile: stoull ``` ### build bpftrace ```shell /usr/bin/mandb: can't write to /var/cache/man/28345: No space left on device ``` ### No space left on device 問題 原來是因為 `lvm` - Logical Volume Management 的關係 > follow the steps on the article below, I just fix the problem >[time=Mon, Aug 17, 2020 2:24 PM] [Ubuntu Server 18.04 LVM out of space with improper default partitioning ](https://askubuntu.com/questions/1106795/ubuntu-server-18-04-lvm-out-of-space-with-improper-default-partitioning) ```shell # We need to resize the logical volume to use all the existing and free space of the volume group $ lvm lvm> lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv lvm> exit # And then, we need to resize the file system to use the new available space in the logical volume $ resize2fs /dev/ubuntu-vg/ubuntu-lv resize2fs 1.44.1 (24-Mar-2018) Filesystem at /dev/ubuntu-vg/ubuntu-lv is mounted on /; on-line resizing required old_desc_blocks = 1, new_desc_blocks = 58 The filesystem on /dev/ubuntu-vg/ubuntu-lv is now 120784896 (4k) blocks long. # Finally, you can check that you now have available space: $ df -h Filesystem Size Used Avail Use% Mounted on udev 3.9G 0 3.9G 0% /dev tmpfs 786M 1.2M 785M 1% /run /dev/mapper/ubuntu--vg-ubuntu--lv 454G 3.8G 432G 1% / ``` # Next read [Learn eBPF Tracing: Tutorial and Examples](http://www.brendangregg.com/blog/2019-01-01/learn-ebpf-tracing.html#Intermediate) 學習 how to use eBPF tracing ## Learn gnuplot -> 來產生 fibdrv 的製圖 * [gnuplot 語法解說和示範](/@sysprog/Skwp-alOg) * [2016q3 Homework1 (phonebook)](/@ktvexe/HkUNXnz6?type=view) * phonebook 作業內涵 * gnuplot 說明 * cache-miss 議題 * perf 分析 ## solve SecureBoot problem Use mokutil to disable secure boot ```shell $ sudo mokutil --disable-validation password length: 8~16 input password: input password again: ``` Check the current state of secure boot ```shell $ mokutil --sb-state SecureBoot disabled Platform is in Setup Mode ``` >still can not load kernel module 觀察 dmesg 後發現 關掉 secure boot 前,還可以正常 load module 關掉後反而無法 證據: ```shell ls -l /dev/fibonacci 找不到東西 ``` execute `make check` 時,出現 ```shell make -C /lib/modules/4.15.0-112-generic/build M=/home/unknowntpo/repo/unknowntpo/fibdrv modules make[1]: Entering directory '/usr/src/linux-headers-4.15.0-112-generic' Building modules, stage 2. MODPOST 1 modules make[1]: Leaving directory '/usr/src/linux-headers-4.15.0-112-generic' make unload make[1]: Entering directory '/home/unknowntpo/repo/unknowntpo/fibdrv' sudo rmmod fibdrv || true >/dev/null rmmod: ERROR: Module fibdrv is not currently loaded ``` >在 vm 上觀察 ```shell $ sudo insmod fibdrv.ko insmod: ERROR: could not insert module fibdrv.ko: Invalid module format ``` ## OscarShiang's [repo](https://github.com/OscarShiang/fibdrv/commit/87e3ec827e3d29e12d681a02f157f2630223db1c) imitate (unsolved) (已回報[錯誤](https://github.com/OscarShiang/fibdrv/commit/6c604859eb2e998fa33201e686e8111c9f25ecf5)) at commit 6c604859eb : Add fast doubling method to test the speed :::danger can't load module ```shell $ make check make -C /lib/modules/4.15.0-112-generic/build M=/home/unknowntpo/repo/OscarShiang/fibdrv modules make[1]: Entering directory '/usr/src/linux-headers-4.15.0-112-generic' Building modules, stage 2. MODPOST 1 modules make[1]: Leaving directory '/usr/src/linux-headers-4.15.0-112-generic' make unload make[1]: Entering directory '/home/unknowntpo/repo/OscarShiang/fibdrv' sudo rmmod fibdrv || true >/dev/null rmmod: ERROR: Module fibdrv is not currently loaded ... ``` 我的開發環境 ```shell $ uname -a Linux unknowntpo 4.15.0-112-generic #113-Ubuntu SMP Thu Jul 9 23:41:39 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux $ cat /proc/version Linux version 4.15.0-112-generic (buildd@lcy01-amd64-027) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #113-Ubuntu SMP Thu Jul 9 23:41:39 UTC 2020 $ cat /etc/os-release NAME="Ubuntu" VERSION="18.04.4 LTS (Bionic Beaver)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 18.04.4 LTS" VERSION_ID="18.04" HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" VERSION_CODENAME=bionic UBUNTU_CODENAME=bionic ``` :::