# 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, ¶m, 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
```
發現仍然有多餘的字元存在,並且程式中沒有考慮到接收失敗的情況。