# Linux 核心專題: 重作 kxo
> 執行人: vicLin8712
### Reviewed by `Hande1004`
> 文中的 " 並且僅可 `r`ead。"
這裡應該是打錯字,請留意。
### Reviewed by `h0w726`
>fget 用於讀取 fp 的20個字元,注意到 C11 標準內提到 fget 僅會讀取到換行符號(或檔案結束)為止,並於最後保留 \0,也就是僅會讀取最多19個 bytes。
可以引用 C 語言規格書內容作為解釋。
### Reviewed by `fcu-D0812998`
>對 atomic_long_t 目的與功能不清楚
可以附上你針對 atomic_long_t 查找的資料,並在更詳細解釋你不懂的地方嗎?
## 任務簡述
重作 [kxo](https://hackmd.io/@sysprog/linux2025-kxo),務必完成所有指定任務,過程中可觀摩同學的成果並予以重現。要額外探討以下: (都該有原始程式碼分析和實驗解讀)
* Linux workqueue 的目標/要解決什麼問題
* atomic operations in Linux kernel device driver
* CMWQ 的設計目標,如何運用在 kxo
* Linux tasklet 的作用是什麼?為何會被棄置?替代方案又是什麼?對 kxo 有何啟發?
## 重做 kxo 專案
### Kxo `xo-user.c` 檔案分析
此檔案示範如何在 userspace 端與 kernel space 進行通訊,此檔案為 user space 端的程式碼。
```C
#define XO_STATUS_FILE "/sys/module/kxo/initstate"
static bool status_check(void)
{
FILE *fp = fopen(XO_STATUS_FILE, "r");
if (!fp) {
printf("kxo status : not loaded\n");
return false;
}
char read_buf[20];
fgets(read_buf, 20, fp);
read_buf[strcspn(read_buf, "\n")] = 0;
if (strcmp("live", read_buf)) {
printf("kxo status : %s\n", read_buf);
fclose(fp);
return false;
}
fclose(fp);
return true;
}
```
`status_check` 用於檢測對應模組是否掛載。
`FILE` 結構體屬於 `<stdio.h>` ,此宣告意即將 `fp` 指向 `XO_STATUS_FILE`,並且僅可 `r`ead。
注意到其指向 `/sys/module/kxo/initstate`,為何不是 `dev` 等檔案系統?
`/sys` 檔案系統主要用於暴露檔案資訊給存取者,而 `/dev` 用於存取硬體資訊,故而放置在 `/sys` 內部。另一個問題是裝置狀態儲存位置需要額外在核心模組寫入嗎?
查看`main.c:492 ret = device_create_file(kxo_dev, &dev_attr_kxo_state);` 發現其利用`linux devices` 所提供的 `device_create_file`,建立一個於 `sys` 的檔案用於儲存 `kxo_dev` 的狀態,當然前面需要先建立 `kxo_dev` 的物件(後續會討論到)。
`fget` 用於讀取 `fp` 的20個字元,注意到 C11 標準內提到 `fget` 僅會讀取到換行符號(或檔案結束)為止,並於最後保留 `\0`,也就是僅會讀取最多19個 bytes。問題是究竟 `fget` 所獲得的 bytes 會有何種形式?回顧到 `fp` 的創建,需回去查看核心模組的原始碼,後續再追蹤,在此先認為他會回傳某些用於判斷模組正常與否的資料。
`strcspn` 用於取出兩者字串一樣的位置,在此例也就是 `read_buf` 出現 `\n` 的位置,將其設置為 0 避免掉換行。
```c
static struct termios orig_termios;
static void raw_mode_disable(void)
{
tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios);
}
static void raw_mode_enable(void)
{
tcgetattr(STDIN_FILENO, &orig_termios);
atexit(raw_mode_disable);
struct termios raw = orig_termios;
raw.c_iflag &= ~IXON;
raw.c_lflag &= ~(ECHO | ICANON);
tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
}
```
`termios` 查詢此結構體的使用,可參考 [termios(3) — Linux manual page](https://www.man7.org/linux/man-pages/man3/termios.3.html) ,此標頭檔提供用於控制終端機,terminal,所需的基本操作。
終端機在此專案中用以呈現下棋步驟,其中步驟由核心模組的演算法所決定。先查看 `raw_mode_enable` ,`tcgetattr` 取得 `STDIN_FILENO` 所對應的檔案描述符 (STDIN_FILENO 實際上 = 0),並將其賦予後者 `orig_termios`。
### LINUX 核心的併行處理
閱讀材料: Linux 核心設計: 中斷處理和現代架構考量
## Linux workqueue 的目標/要解決什麼問題
檢視 `workqueue.h` 程式碼
```c
struct delayed_work {
struct work_struct work;
struct timer_list timer;
/* target workqueue and CPU ->timer uses to queue ->work */
struct workqueue_struct *wq;
int cpu;
};
```
發現結構體 `work_struct`、`timer_list`,以及`workqueue_struct`。查閱其對應的標頭檔以釐清內部元素,首先是宣告`work_struct` 結構體之標頭檔。對應程式碼如下
```c
struct work_struct {
atomic_long_t data;
struct list_head entry;
work_func_t func;
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
};
```
對 `atomic_long_t` 目的與功能不清楚。
## Atomic Operation in Linux Kernel Device Driver
### 目的