# ktcp ## kecho ### 修正 kthread_run 失敗時的錯誤回傳 > pull request https://github.com/sysprog21/kecho/pull/13 我發現在 `kecho_init_module` 裡面,如果 `kthread_run` 失敗了會去關閉 socket,但是依然會回傳 0,讓核心模組成功的被掛載。這樣不是預期行為,而且在移除模組的時候會去重複的釋放資源,造成核心錯誤,於是送了這個 pull request。我利用直接把 `echo_server` 指定成 `ERR_PTR(-ENOMEM)` 去模擬這個錯誤的發生,並且如預期的遇到了這樣的錯誤。 ```cpp echo_server = kthread_run(echo_server_daemon, &param, MODULE_NAME); if (IS_ERR(echo_server)) { printk(KERN_ERR MODULE_NAME ": cannot start server daemon\n"); close_listen(listen_sock); } return 0; ``` 我這個修改讓它在失敗的時候會回傳對應的錯誤碼: ```diff +return PTR_ERR(echo_server); ``` 當錯誤發生時,如預期的掛載核心模組會失敗,並且跳出對應的錯誤訊息: ``` insmod: ERROR: could not insert module kecho.ko: Cannot allocate memory ``` ### `ktcp` 運作原理 首先成功建立 socket,然後建立一個 kernel thread 去跑 `echo_server_daemon`。`echo_server_daemon` 會監聽新的連線,偵測到新的連線的時候會建立一個新的 `work_struct`,並且利用 workqueue 做排程,callback function 是 `echo_server_worker`。而被建立的這個 `work_struct` 是內嵌在 `kecho` 這個結構體裡面的,`kecho` 會額外去紀錄他的 socket,並且能在 `echo_server_worker` 中使用 `container_of` 獲得。至於 `echo_server_worker` 就是負責與對應的 socket 做溝通。 ### `user-echo-server` 運作原理 這是一個在使用者空間運行的伺服器,它使用 `epoll` 達成 I/O multiplexing。 - `epoll_create` 建立新的 `epoll`,回傳一個描述子,之後利用這個描述子來對它進行操作 - `epoll_ctl` 可以對 `epoll` 中的元素進行增加修改或移除,這裡使用 `EPOLL_CTL_ADD` 去做增加 - `epoll_wait` 可以等待在 interest list 中在觀察的那些檔案描述子是否準備好要互動了,回傳可以互動的數量,並且在 `events` 中留下資料(包括檔案描述子) 這裡,一開始在 `epoll` 中放了 `listener`,每次有他的事件發生代表有客戶端要來進行連線了,這個時候,如果有成功建立連線就會在 `epoll` 中放新的檔案描述子。另外,這裡的連線都是 nonblock 狀態,使用 `setnonblock` 設定的,所以在 `accept` 的時候如果沒有人來連線就會直接回傳。至於如果事件的檔案描述子不是 `listener` 就代表是客戶端傳來訊息,會呼叫 `handle_message_from_client` 去處理。