owned this note
owned this note
Published
Linked with GitHub
# 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`