# 2019q1 Homework5 (daemon)
contributed by < `F74021200` >
在 clone 給定的[程式碼](https://github.com/sysprog21/kecho)後,執行 make ,在 make 的過程中會出現以下的錯誤訊息:
```shell
echo >&2 " ERROR: Kernel configuration is invalid."; \
```
但是仍有產生 .ko 檔,並可載入 kernel 。
make 結束後,執行:
```shell
sudo insmod fastecho.ko
```
將 module 載入 kernel 。
成功載入後,執行:
```shell
telnet localhost 12345
```
透過 telnet 連線至 echo server , fastecho ,預期會有以下畫面:
```shell
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
```
接著於鍵盤輸入:
```shell
1
```
會有以下畫面:
```shell
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
1
1
:P�&
```
會有一行亂碼。
開啟另一 Terminal ,使用 dmesg 查看 printk 輸出的資訊如下:
```shell
[233191.127281] fastecho: socket create ok....
[233191.127294] fastecho: setsockopt ok....
[233191.127301] fastecho: socket bind ok....
[233191.127308] fastecho: socket listen ok....
[233207.182909] fastechostrlen when malloc:14
[233207.182920] fastecho: start get response
[233340.704296] fastecho: get request = 1
:P\xe1&V \xa97
[233340.704309] fastecho: start send request.
[233340.704369] fastecho: send request = 1
:P\xe1&V \xa97
[233340.704375] fastecho: start get response
```
關閉 telnet ,並卸載 fastecho module 。
查看 get_request() 的使用,發現 get_request() 在 echo_server_worker() 中被使用,傳入的參數, buf ,在 echo_server_worker() 中被宣告並配置空間,如下所示:
```click=
static int echo_server_worker(void *arg)
{
struct socket *sock;
unsigned char *buf;
int res;
sock = (struct socket *) arg;
allow_signal(SIGKILL);
allow_signal(SIGTERM);
buf = kmalloc(BUF_SIZE, GFP_KERNEL);
if (!buf) {
printk(KERN_ERR MODULE_NAME ": kmalloc error....\n");
return -1;
}
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));
kernel_sock_shutdown(sock, SHUT_RDWR);
sock_release(sock);
kfree(buf);
return 0;
}
```
但使用前未將 buf 所指向的空間初始化;在 get_request() 中,若取得的字串沒覆蓋掉已存在亂碼的空間,這些亂碼將會於輸出時顯現,導致非預期結果;因此,於 echo_server.c 中,進入 get_request() 前,都先以 memset() 將 buf 初始化,如下第 20 行:
```click=
static int echo_server_worker(void *arg)
{
struct socket *sock;
unsigned char *buf;
int res;
sock = (struct socket *) arg;
allow_signal(SIGKILL);
allow_signal(SIGTERM);
buf = kmalloc(BUF_SIZE, GFP_KERNEL);
if (!buf) {
printk(KERN_ERR MODULE_NAME ": kmalloc error....\n");
return -1;
}
printk(MODULE_NAME "strlen when malloc:%ld\n", strlen(buf));
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));
kernel_sock_shutdown(sock, SHUT_RDWR);
sock_release(sock);
kfree(buf);
return 0;
}
```
重新 make 並載入 fastecho.ko ,執行 telnet 後,不再有亂碼產生,但是游標會停在上個輸出的第一個字元,導致在 Terminal 畫面中,這次輸入的字元會覆蓋掉上次輸出的字元,導致這些字元混在一起。
發現將 send_request() 中,第 14 行與第 18 行的 strlen(buf) 改成 BUF_SIZE 後,上述問題便解決,但不知為什麼,目前仍在尋找原因。
```click=
static int send_request(struct socket *sock, unsigned char *buf, size_t size)
{
int length;
struct kvec vec;
struct msghdr msg;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
vec.iov_base = buf;
vec.iov_len = strlen(buf);
printk(MODULE_NAME ": start send request.\n");
length = kernel_sendmsg(sock, &msg, &vec, 1, strlen(buf) - 1);
printk(MODULE_NAME ": send request = %s\n", buf);
return length;
}
```