contributed by < hankluo6
>
insmod
最後會呼叫到 load_module
,在 load_module
中會先透過 find_module_sections
設置 module 的指標到對應的 section,接著 parse_args
便能將對應的參數寫入。
在 find_module_sections
中,struct module
是代表核心模組主要的結構,將 mod->kc
指向 __param
這個 section,並設置 mod->num_kp
的值。
parse_args
將使用者輸入的每個參數都傳到 parse_one
檢查,parse_one
將使用者提供的參數名字與 __param
section 內的所有參數名字比對,如果相同則透過 params[i].ops->set
設置參數。
所以 module_param
應該要將參數植入到 __param
section,並提供對應的 ops
:
可以看到最後會透過 __module_param_call
展開,其中 __used __section("__param")
證明了會將這些參數放置在 __param
section。而實際設置參數 ops->set
函式的 ops
會在 module_param_named
時設置成 ¶m_ops_##type
傳入,param_ops_##type
會被展開成 param_ops_ushort
或 param_ops_bool
等預先定義好的 type,其中也有定義好每個 type 對應的 set
操作,透過對應的 set
函式便能將資料寫入。
透過 socket(2)
建立 socket,setnonblock
將這個 sockeet 設置為 no blocking,bind(2)
將 socket 與 address 綁定在一起。
listen(2)
將 socket 開始監聽,使其能夠接收 client 端的請求連線。TCP 在 kernel 中會維護兩個 queue,第一個 queue 用來儲存正在進行 three-way handshaking 中的 request,第二個 queue 會存放已經處理好在等待 accept
的 request,而 backlog
參數指的是可以指定這兩個 queue 的總和大小。
epoll(7)
可以同時監控多個 file descriptions 並判斷哪些 fd 有資料可寫入或讀取:
epoll_create(2) creates a new epoll instance and returns a file
descriptor referring to that instance. (The more recent
epoll_create1(2) extends the functionality of epoll_create(2).)Interest in particular file descriptors is then registered via
epoll_ctl(2), which adds items to the interest list of the
epoll instance.epoll_wait(2) waits for I/O events, blocking the calling thread
if no events are currently available. (This system call can be
thought of as fetching items from the ready list of the epoll
instance.)
將要監聽的 listener
透過 epoll_ctl
註冊到 epoll
當中,epoll_wait
當有 client 連接時,便會回傳。在 for
迴圈中,透過 accept(2)
將這個 client 連接,並將 client 的 fd 透過 epoll_ctl
放到 epoll
中等待接收資料。而 push_back_client
透過 linked list 紀錄現在有哪些 client 連接。
當 epoll_wait
回傳的 events 不是 listener
時,表示 client 端有資料傳入,進入 handle_message_from_client
處理。
handle_message_from_client
透過 recv
及 send
將 client 傳來的資料回傳,如果 len
為 0,表示沒有資料傳入,可以認為 client
端以被關閉,利用 delete_client
將 client 從 linked list 中移除。
bench.c
create_worker
會透過 pthread_create
建立執行緒執行 bench_worker
函式,而為了確保每個執行緒能在相同的時間執行,pthread_cond_wait
讓每個執行緒等待 condition 發生,建議完執行緒後,pthread_cond_broadcast
喚醒所有等待的執行緒。bench_worker
便開始建立 TCP 連線,gettimeofday
紀錄 recv
及 send
的時間。
kecho 的速度比 user-echo-server 快將近 10 倍左右,這是因為 user space 的系統呼叫 (如 listen
, accept
) 最後也會呼叫到 kernel 內的 kernel_listen
及 kernel_accept
。
系統呼叫的成本雖然整體來說持續降低,但終究無法消弭,我們今年發表 Effective System Call Aggregation (ESCA) 來降低系統呼叫過程的 CPU mode switch 的衝擊。
linux2022