# 2019q1 Homework9 (daemon) contributed by < `zodf0055980` > ###### tags: `Linux 核心設計` ## 修改 首先先嘗試傳輸一些簡單的字串 ```shell= [ 336.832786] fastecho: socket create ok.... [ 336.832788] fastecho: setsockopt ok.... [ 336.832791] fastecho: socket bind ok.... [ 336.832793] fastecho: socket listen ok.... [ 352.349299] fastecho: start get response [ 392.883371] fastecho: get request = aaa 3d\xe0f\xea\xfd\xb5U [ 392.883373] fastecho: start send request. [ 392.883402] fastecho: send request = aaa 3d\xe0f\xea\xfd\xb5U [ 392.883403] fastecho: start get response [ 396.968222] fastecho: get request = bbb 3d\xe0f\xea\xfd\xb5U [ 396.968224] fastecho: start send request. [ 396.968258] fastecho: send request = bbb 3d\xe0f\xea\xfd\xb5U [ 396.968259] fastecho: start get response [ 400.748929] fastecho: get request = bbb 3d\xe0f\xea\xfd\xb5U [ 400.748932] fastecho: start get response [ 400.748935] fastecho: get request = bbb 3d\xe0f\xea\xfd\xb5U [ 400.748936] fastecho: start send request. [ 400.749006] fastecho: send request = bbb 3d\xe0f\xea\xfd\xb5U ``` 發現最後傳輸的字串會多執行好幾次 get request 和 send request,以及傳送字串有產生亂碼,並且亂碼每次重新執行的結果皆不同。因此觀看程式碼: ```clike static int fastecho_init_module(void) { int error = open_listen(&listen_sock); if (error < 0) { printk(KERN_ERR MODULE_NAME ": listen socket open error\n"); return error; } param.listen_sock = listen_sock; 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; } ``` 可以看到在 init_module 的函式中利用 kthread_run 去在背景程式中執行一個 server 端的程序。 ```clike while (!kthread_should_stop()) { res = get_request(sock, buf, BUF_SIZE - 1); if (res <= 0) { if (res) { printk(KERN_ERR MODULE_NAME ": get request error = %d\n", res); } break; } res = send_request(sock, buf, strlen(buf)); if (res < 0) { printk(KERN_ERR MODULE_NAME ": send request error = %d\n", res); break; } } res = get_request(sock, buf, BUF_SIZE - 1); res = send_request(sock, buf, strlen(buf)); ``` 而程序中透過 while (!kthread_should_stop()) 去確保可以一直執行到我們把它關閉。而關閉後則會在傳送和接收字串一次,因此導致 dmesg 的訊息會重複。我首先將它註解調並在執行 get_request 前先透過 memset 把 buffer 給清空。 ```clike while (!kthread_should_stop()) { memset(buf,0,BUF_SIZE); res = get_request(sock, buf, BUF_SIZE - 1); if (res <= 0) { if (res) { printk(KERN_ERR MODULE_NAME ": get request error = %d\n", res); } break; } res = send_request(sock, buf, strlen(buf)); if (res < 0) { printk(KERN_ERR MODULE_NAME ": send request error = %d\n", res); break; } } // res = get_request(sock, buf, BUF_SIZE - 1); // res = send_request(sock, buf, strlen(buf)); ``` ```shell [ 2829.146997] fastecho: socket listen ok.... [ 2831.793319] fastecho: start get response [ 2833.345299] fastecho: get request = aaa [ 2833.345301] fastecho: start send request. [ 2833.345357] fastecho: send request = aaa [ 2833.345359] fastecho: start get response [ 2835.341717] fastecho: get request = bbb [ 2835.341720] fastecho: start send request. [ 2835.341764] fastecho: send request = bbb [ 2835.341766] fastecho: start get response [ 2838.395686] fastecho: get request = ``` 發現雖然沒有亂碼了,但顯示的訊息仍然可有換行字元的存在,並且最後還會在傳送一個空的字串。 [kernel-recvmsg](https://www.kernel.org/doc/htmldocs/networking/API-kernel-recvmsg.html) 內有說到: The returned value is the total number of bytes received, or an error. 嘗試去把接收到的字串長度顯示出來: ``` [ 3254.286760] fastecho: start get response [ 3255.487711] fastecho: length = 4 [ 3255.487713] fastecho: get request = aa [ 3255.487714] fastecho: start send request. [ 3255.487772] fastecho: length = 3 [ 3255.487773] fastecho: send request = aa ``` 發現仍然有多餘的字元存在,並且程式中沒有考慮到接收失敗的情況。