contributed by < flawless0714
>
一般系統呼叫是以 synchronous 的方式完成,這種典型的實做方式在系統呼叫密集型(例如:網頁伺服器)的軟體中容易成為效能的瓶頸,主要原因有兩個:
而 FlexSC 則是以 asynchronous 的方式來實做系統呼叫,並分別指定特定核心(kthread_bind(), sched_setaffinity())來處理系統呼叫,下圖為其執行之示意圖:
(取自 OSBI'10 FlexSC)
這種 asynchronous 的系統呼叫實做方式除了沒有上述造成效能瓶頸的問題外,還增加了 cache locality 以及減少 CPU mode switch 的發生,這些是 FlexSC 效能優於典型系統呼叫的關鍵點。
下圖為 FlexSC 在 Linux kernel v2.6.33 上的效能分析:
(取自 OSBI'10 FlexSC slide)
(取自 OSBI’10 FlexSC slide)
如需單獨編譯此 module,需把 makefile 裡的 SUBDIR
(SUBDIR 在 kernel 5.3 版後要被棄置了)替換成 M=
(kernel header 裡的 makefile 使用 M
來取得外部程式碼(syshook)的路徑),否則 make
會往上一層 directory 找其他程式碼(fs, mm, etc.)編譯,並且忽略 syshook
。
目前是用 host 機上的 .config 去編譯 kernel 再搭配手動把幾個 virtio 相關的 module 編進 kernel 才可以成功掛載共享資料夾。後來發現是 guest 的 .config 有少開 module。
原先以為 CMWQ 跟早期的 workqueue (create_workqueue()) 是並存的,但查詢後發現其實在 v2.6 的 commit 後 workqueue 就被更新成以 CMWQ 實做的 workqueue 了..。
將 work 安排到給定 workqueue 中。通常執行 work 的 CPU 是 caller 的 CPU,只有 CPU 正在 IDLE (可能發生於 workqueue 有一段時間沒有收到工作) 才會交給其他 CPU 執行。內部其實是以 WORK_CPU_UNBOUND 去呼叫 queue_work_on()。
推測效能在 syscall 頻率高時會好的原因是 processor structures (儲存於 cache) 在 user space 沒有嚴重的 eviction (因為執行沒多久就切回 kernel space)。
Cache 的最小儲存單位。現代主流 CPU 的 cache line 大小為 64 bytes。
由 kthread_create() 與 kthread_run() 包裝而成。
在 calling process 的 timeslice 還沒結束前,手動放棄 calling process 的 CPU 資源。當放棄 CPU resource 的這個 process 再一次的被 scheduler 選中,其會從離開前的 context (即呼叫 scheduler() 的地方)繼續執行。
此 API 需於 kthread 尚未被喚醒前呼叫。換句話說,若 kthread 有綁定 CPU 的需求,我們就不該使用 kthread_run() 來建立 kthread。
防止 process 中給定區塊記憶體被置換到 swap 中。在此應用中,若 syscall page 被置換到 swap 將對應用程式的效能造成直接影響。
M 表示 application 的 thread,N 則為 paper 中提到的 kernel-visible thread (pthread)。
經過測試,使用此 API 設定 process 的 CPU affinity 後,其生成的 pthread 也有著同樣的 CPU affinity。因此 pthread_setaffinity_np() 可用於執行時期修改指定 pthread 的 CPU affinity。
撰寫 device driver 或 syscall 時若需要建立 kernel thread 的話應該使用此 API,其建立的 thread 有著乾淨的 context,即不需要擔心 kernel space 的資訊由此 thread 流出。此外,此 thread 的 parent 為 kthreadd (kthread daemon),而使用 kernel_thread() 建立的 thread 的 parent 則為 init 或其他 kernel thread,這是 kthread_create() 有著乾淨的 context 的原因之一。
此系統呼叫即為 mmap,而若需在 kernel space 使用的話則直接呼叫 sys_mmap_pgoff() 即可。值得注意的是它在 commit 被移除,取而代之的是 ksys_mmap_pgoff()。
roundup
用於取得大於 x 且最接近 x 之 y 的倍數的數值(i.g. roundup(19, 4) –> 20),而 rounddown
則用於取得小於 x 且最接近 x 之 y 的倍數的數值。而另外還有 round_up
與 round_down
,兩組 macro 差別僅在於後者的 y 必須是2的羃次。通常用於配置對齊之記憶體 (page aligned)。
前者用於宣告並初始化 work (struct work_struct
),而後者則是用於初始化已經宣告過的 work。
使用於欲釋放的記憶體可能由 kmalloc() 或 vmalloc() 配置時。如果確定是兩者之一則建議用其專用 API (kfree(), vfree()),較有效率。
在 x86_64 與 x86 中,kernel space 與 user space 的 address space 沒有完整的劃分,他們僅靠 boundary 來區隔兩者的 address space,在這種情況下 __user
的用途為警告開發人員現在在操作的指標的內容是來自 user space 的。而在 PowerPC 中 address space 則是有明顯的劃分,更詳細的説 kernel 與 user 的 address space 其實是完全隔離的,所以在 PowerPC 架構下使用 __user
時,我們不僅提醒自己這個指標的內容屬於 user space,同時也讓 kernel 知道這個指標的內容需要轉換成 user space 的記憶體位置。
kernel 非 busy-waiting 的 delay API,delay 時間的參數是 jiffies
,一般是使用 HZ
(排程器每秒運作次數(scheduler())),換句話說,如果我們需要 delay 三秒,我們可以以 HZ * 3
作為 argument 帶入。呼叫這個 API 之前,如果我們把 task 的 state 設為 TASK_INTERRUPTIBLE
,那麼我們可以在睡眠期間透過 signal 把這個 task 喚醒,反之則是睡到 timeout。
若要在 kernel 中使用 fd 相關操作的話, kernel 有提供 kerenl_read(), kernel_write()。這兩個 API 是在 v4.14 後加入的,而在這之前使用的 vfs_read() 與 vfs_write() 已經被 unexport,也就是說我們沒辦法在 kernel module 中呼叫了。
將 virtual address 轉為 physical address。
將 kernelspace 之記憶體映射到 user space。
參考這裡。
僅 dump call stack,而 BUG_ON 則是觸發 panic。
查詢了編譯器警告(useless type qualifier in empty declaration
)才知道 volatile
不能用在宣告中,只有在定義時使用才有效。也就是說,如果宣告有加 volatile
,但定義沒加,則還是會被視為非 volatile
的變數。
相關的 driver (virtio, 9p) 要編進 kernel 或讓 initramfs 載入,否則掛載會失敗(e.g. no such device(這坑花了快半天才爬出來..,一直以為 driver 都有選到了,結果有些是 module…))。
為了安全考量,printk 的 specifier %p
會將給定的記憶體位置做 hash 後才將其印出。如欲印出真實位置則需使用 %px
或是 %lx
,前者較推薦,因為 grep 的時候比較方便找到。
兩者都是用於除錯 kernel 用,特點分別為:
scheduling scope
Scope determines how many threads≈and which threads≈a given thread must compete against when it's time for the scheduler to select one of them to run on a free CPU.
Some operating systems know little about thread, some of them may schedule process to run instead of thread. In other words, a given implementation may allow you to schedule threads either in process scope or in system scope.
同學的 FlexSC 筆記
TSC (Time Stamp Counter)
Buildroot processor march type
syscall on i386
x86 Instruction Set Reference
(SYSENTER)
x86 instruction (sysenter)
Linux 系統呼叫分析
difference of yield_schedule and schedule
Sleeping in kernel thread
task set
CPU Affinity
EXPORT_SYMBOL_GPL
==undone== syscall wrapper
wake_up_process
current() after v2.6
==undone== Linus spin lock talk
==undone== Add function to init
kthread_create 與 kernel_thread 的差別
asmlinkage (syscall)
kernel code, yield()
__user (pointer to user address space)
X86 Assembly/Interfacing with Linux
schedule_timeout()
Linux waitqueue (task_struct->state)
GCC attribute (address space)
introduction using of CMWQ workqueue
Anatomy of a system call (syscall wrapper), additional content
linux2019