# 2019q1 Homework5 (daemon) contributed by < ` JulianATA ` > ## kecho 缺失 ### 亂碼問題 ```bash $ telnet localhost 12345 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. a a Ф�Q ``` 查看一下 `dmesg` ``` [65748.443421] fastecho: start get response [65752.210281] fastecho: get request = a Ф\xffffffedQ \xfffffff8\xffffff97 [65752.210282] fastecho: start send request. [65752.210310] fastecho: send request = a Ф\xffffffedQ \xfffffff8\xffffff97 [65752.210310] fastecho: start get response [65800.016714] fastecho: get request = a Ф\xffffffedQ \xfffffff8\xffffff97 [65800.016715] fastecho: start get response [65800.016716] fastecho: get request = a Ф\xffffffedQ \xfffffff8\xffffff97 [65800.016716] fastecho: start send request. [65800.016737] fastecho: send request = a Ф\xffffffedQ \xfffffff8\xffffff97 ``` 發現兩個問題 * 輸入時,就有產生亂碼。 * 單次操作,但是多次 get, send request ### 亂碼處理 In ` echo_server.c `, buffer is found to be initialized in `echo_server_worker` . add `memset` in while loop and initialization. ```clike buf = kmalloc(BUF_SIZE, GFP_KERNEL); memset(buf,'\0',BUF_SIZE); ``` ```clike while (!kthread_should_stop()) { memset(buf,'\0',BUF_SIZE); . . . ``` 但是,處理完後開始出現以下問題。 ``` insmod: ERROR: could not insert module fastecho.ko: Address already in use ``` ### Address already in use 問題 ```clike while(!kthread_should_stop()){ skip } kernel_sock_shutdown(sock, SHUT_RDWR); sock_release(sock); kfree(buf); return 0; } ``` 刪除在 `kthread_should_stop()` 之後的 send, get 後解決。 ### 為什麼會多次 get, send request ### Buffer overflow 的行為與問題 首先,為了觀察方便, buff_size 先減少為 4 bytes 。 ```bash $ telnet localhost 12345 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. 123456789 124578 ``` dmesg : ```bash [ 1072.201404] fastecho: socket create ok.... [ 1072.201406] fastecho: setsockopt ok.... [ 1072.201407] fastecho: socket bind ok.... [ 1072.201409] fastecho: socket listen ok.... [ 1185.456864] fastecho: start get response [ 1190.738053] fastecho: get request = 123 [ 1190.738056] fastecho: start send request. [ 1190.738100] fastecho: send request = 123 [ 1190.738102] fastecho: start get response [ 1190.738105] fastecho: get request = 456 [ 1190.738106] fastecho: start send request. [ 1190.738123] fastecho: send request = 456 [ 1190.738124] fastecho: start get response [ 1190.738127] fastecho: get request = 789 [ 1190.738128] fastecho: start send request. [ 1190.738140] fastecho: send request = 789 [ 1190.738141] fastecho: start get response [ 1190.738145] fastecho: get request = [ 1190.738146] fastecho: start send request. [ 1190.738157] fastecho: send request = [ 1190.738158] fastecho: start get response [ 1203.152373] fastecho: get request = ``` 觀察發現在 buff_size = 4 bytes 的情況下,每次會傳入三個 char 。 推測為四個 byte 中,一個為中止符,而剩下三個為傳入的 char 。 而回傳後則少了一個 byte 。 比較 `get_request` 以及 `send_request` : ```clike length = kernel_recvmsg(sock, &msg, &vec, size, size, msg.msg_flags); ``` ```clike length = kernel_sendmsg(sock, &msg, &vec, 1, strlen(buf)-1); ``` 可以看到在 send 以及 receive 中,兩者獲取 size 的方法不同。 追本溯源到 `echo_server_worker` 後,可以發現傳入的 size 變數也不同。 ```clike res = get_request(sock, buf, BUF_SIZE - 1); ``` ```clike res = send_request(sock, buf, strlen(buf)); ``` ### 測試傳入與傳出 buffer size #### 沒有 overflow 為了觀察方便, buff_size 先設定為 1024 bytes 。 測試輸入 123456789 以下為 `dmesg` : ```bash [ 2478.628281] fastecho: socket create ok.... [ 2478.628283] fastecho: setsockopt ok.... [ 2478.628284] fastecho: socket bind ok.... [ 2478.628286] fastecho: socket listen ok.... [ 2485.160850] fastecho: start get response ,buffer size = 1023 [ 2488.082356] fastecho: get request = 123456789 [ 2488.082360] fastecho: start send request ,buffer size = 10 [ 2488.082406] fastecho: send request = 123456789 [ 2488.082409] fastecho: start get response ,buffer size = 1023 [ 2497.380246] fastecho: get request = ``` 在沒有 overflow 的情況下,設計傳出的 buffer size 為傳入字串的全長度(包含終止符號)。 > 猜測為節省 buffer 大小,以提高速度。 待驗證。 > [name=Julian Fang] #### overflow 為了觀察方便, buff_size 設定為 10 bytes 。 測試輸入 123456789 返回為 12345678 以下為 `dmesg` : ```bash [ 2731.251484] fastecho: socket create ok.... [ 2731.251487] fastecho: setsockopt ok.... [ 2731.251488] fastecho: socket bind ok.... [ 2731.251490] fastecho: socket listen ok.... [ 2739.128242] fastecho: start get response ,buffer size = 9 [ 2741.312180] fastecho: get request = 123456789 [ 2741.312184] fastecho: start send request ,buffer size = 8 [ 2741.312230] fastecho: send request = 123456789 [ 2741.312232] fastecho: start get response ,buffer size = 9 [ 2741.312237] fastecho: get request = [ 2741.312238] fastecho: start send request ,buffer size = 1 [ 2741.312256] fastecho: send request = [ 2741.312257] fastecho: start get response ,buffer size = 9 [ 2747.346103] fastecho: get request = ``` 在 overflow 的情況下,回傳丟失了一個 byte 。 ### 著手修改 buffer size 機制 in `send_request` ```clike length = kernel_sendmsg(sock, &msg, &vec, 1, strlen(buf)); ``` 修改為與 kvec 物件 vec 一樣為 strlen(buf) 。 測試 buffer size = 4 且 overflow 的情況。 輸入 123456789 回傳 123456789 dmesg: ```bash [ 3837.205080] fastecho: socket create ok.... [ 3837.205081] fastecho: setsockopt ok.... [ 3837.205083] fastecho: socket bind ok.... [ 3837.205085] fastecho: socket listen ok.... [ 3841.401241] fastecho: start get response ,buffer size = 3 [ 3846.510682] fastecho: get request = 123 [ 3846.510685] fastecho: start send request ,buffer size = 3 [ 3846.510734] fastecho: send request = 123 [ 3846.510736] fastecho: start get response ,buffer size = 3 [ 3846.510740] fastecho: get request = 456 [ 3846.510741] fastecho: start send request ,buffer size = 3 [ 3846.510751] fastecho: send request = 456 [ 3846.510752] fastecho: start get response ,buffer size = 3 [ 3846.510754] fastecho: get request = 789 [ 3846.510756] fastecho: start send request ,buffer size = 3 [ 3846.510775] fastecho: send request = 789 [ 3846.510777] fastecho: start get response ,buffer size = 3 [ 3846.510780] fastecho: get request = [ 3846.510781] fastecho: start send request ,buffer size = 1 [ 3846.510793] fastecho: send request = [ 3846.510794] fastecho: start get response ,buffer size = 3 [ 3912.415146] fastecho: get request = ``` 成功在 overflow 的情況下,沒有丟失 byte ! 測試 buffer size = 1024 且 overflow 的情況。 輸入 123456789 回傳 123456789 dmesg: ```bash [ 4074.828316] fastecho: socket create ok.... [ 4074.828318] fastecho: setsockopt ok.... [ 4074.828320] fastecho: socket bind ok.... [ 4074.828321] fastecho: socket listen ok.... [ 4076.760056] fastecho: socket closed .... [ 4078.304170] fastecho: socket create ok.... [ 4078.304171] fastecho: setsockopt ok.... [ 4078.304173] fastecho: socket bind ok.... [ 4078.304174] fastecho: socket listen ok.... [ 4082.805048] fastecho: start get response ,buffer size = 1023 [ 4085.635011] fastecho: get request = 123456789 [ 4085.635014] fastecho: start send request ,buffer size = 11 [ 4085.635054] fastecho: send request = 123456789 [ 4085.635057] fastecho: start get response ,buffer size = 1023 [ 4092.186235] fastecho: get request = ``` 成功在沒有 overflow 的情況下,使用 buffer size + 1 byte 回傳。( 第 10 byte 應為換行符號 ) > 推測其中多的 1 byte 為終止符號。 > [name=Julian Fang] ## Concurrence ### 效能測試 使用 python 嘗試實做 效能測試 ,並以 matplotlib 製圖。 以 thread 配置 telnet 連線, 可調整以下參數: * Client 數量 * Request 數量 * 重複次數(最後秒數為平均) * Timeout ```python def connect_and_send(Host,Port, number, Request_num, timeout): tn = telnetlib.Telnet(Host,Port,timeout = 10) for i in range (Request_num): mesg = ("Telnet No."+str(number)+",Write No"+str(i)+"\n").encode('ascii') tn.write(mesg) tn.read_until(mesg) tn.close() ``` ```python def concurrent_test(Host, Port, Client_num , Request_num,timeout): threads = [] for i in range(Client_num): threads.append(threading.Thread(target = connect_and_send, args = (Host,Port,i,Request_num,timeout,))) for i in range(Clinent_num): threads[i].start() for i in range(Client_num): threads[i].join() return ``` --- Client = 20 Request = 20 Repeat = 5 Timeout = 10 實驗輸出: ![](https://i.imgur.com/sXHNVHZ.png) --- Client = 40 Request = 5 Repeat = 5 Timeout = 10 實驗輸出: ![](https://i.imgur.com/jJY860p.png) --- Client = 50 Request = 20 Repeat = 5 Timeout = 10 實驗輸出: ![](https://i.imgur.com/RLEx5eK.png) ![](https://i.imgur.com/CYTvsZp.png) --- 可以看出來在 client > 30 的情況下,回應時間開始顯著的增加。 --- ### 加入 Concurrency Management Work Queue ###### tags: `Cprogramming`