# 2019q1 Homework5 (daemon) contributed by < `shengyuu` > - [作業要求](https://hackmd.io/s/SkLygcAiV) 按照作業要求下載並編譯 `kecho` ``` $ git clone https://github.com/sysprog21/kecho $ cd kecho $ make ``` ## `kecho` 程式碼 實作的缺失 先將 `fastecho.ko` 核心模組載入,並使用 `telnet` 命令連接到 `localhost` ``` $ sudo insmod fastecho.ko $ telnet localhost 12345 ``` 其中 `12345` 是 `port number`,定義在 `fastecho_module.c` 內 ```c #define DEFAULT_PORT 12345 ``` 執行 `telnet` 命令後會出現這樣的視窗 ``` Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. ``` 試著在這裡輸入任意字串 ``` Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. hello! hello! ��k ``` **從這裡可以觀察到 `kecho` 傳送回來的字串會包含奇怪的字元** 追蹤 `echo_server.c` 後可以發現 `kecho` 是用 `get_request()` 函式接收我們輸入的訊息,並透過 `send_request()` 傳回我們輸入的訊息,並將訊息用 `printk` 印出 ``` c /* get msg */ static int get_request(struct socket *sock, unsigned char *buf, size_t size) { struct msghdr msg; struct kvec vec; int length; /* kvec setting */ vec.iov_len = size; vec.iov_base = buf; /* msghdr setting */ msg.msg_name = 0; msg.msg_namelen = 0; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_flags = 0; printk(MODULE_NAME ": start get response\n"); /* get msg */ length = kernel_recvmsg(sock, &msg, &vec, size, size, msg.msg_flags); printk(MODULE_NAME ": get request = %s\n", buf); //printk(MODULE_NAME "buf_size = %d\n", strlen(buf)); return length; } ``` 使用 `dmesg` 命令看 `printk` 印出的 `buf` 裡面裝了什麼 ``` [ 2548.119722] fastecho: start get response [ 2551.493945] fastecho: get request = hello! \xb0\xd3k V [ 2551.493948] fastecho: start send request. [ 2551.494001] fastecho: send request = hello! \xb0\xd3k V [ 2551.494003] fastecho: start get response ``` 原本預期 `buf` 只裝我們傳送過去的 `hello!` ,但看起來 `buf` 裡面還有存著其他東西並且一起並印出來 再仔細觀察可以發現 `hello!` 後面其實是先空了一行才印出其他字串,猜想 `hello!` 後面應該是接著一個 `\n` ,而 `\n` 應該是我們輸入完字串按下 `enter` 鍵後產生的 我們可以利用每次輸入最後都會按下的 `enter` 鍵來觀察未初始化的 `buf` 中那一些值是我們要的值,哪一些對我們來說是亂碼 在 `echo_server.c` 中的 `get_request()` 函式內,手動將 `kernel_recvmsg` 拿到的 `buf` 的 `\n` 改成 `\0`,以下是更改後的 `get_request` ```c static int get_request(struct socket *sock, unsigned char *buf, size_t size) { struct msghdr msg; struct kvec vec; int length; /* kvec setting */ vec.iov_len = size; vec.iov_base = buf; /* msghdr setting */ msg.msg_name = 0; msg.msg_namelen = 0; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_flags = 0; printk(MODULE_NAME ": start get response\n"); /* get msg */ length = kernel_recvmsg(sock, &msg, &vec, size, size, msg.msg_flags); /* replace '\n' by '\0'*/ int l = 0; while(1) { if(buf[l] == '\n') { buf[l] = '\0'; break; } l++; } printk(MODULE_NAME ": get request = %s\n", buf); //printk(MODULE_NAME "buf_size = %d\n", strlen(buf)); return length; } ``` 測試實驗結果 ``` Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. hello! hello! ``` ``` $dmesg [ 4827.660377] fastecho: socket create ok.... [ 4827.660382] fastecho: setsockopt ok.... [ 4827.660386] fastecho: socket bind ok.... [ 4827.660390] fastecho: socket listen ok.... [ 4843.881880] fastecho: start get response [ 4848.824884] fastecho: get request = hello! [ 4848.824889] fastecho: start send request. [ 4848.824940] fastecho: send request = hello! [ 4848.824944] fastecho: start get response ``` ###### tags: `Linux 核心設計 2019`