# 第 9/10/11/12 週課程問答簡記
> 測驗 2 中 `QUEUE_STRUCT` 的 struct member 後面多 padding 用意為何?
使每個 struct member 都佔一個 cacheline 的大小,若是將每個 member 緊湊的擺在同個 cacheline 大小的空間內,每次一有變更就要發一次 cache invalidate 的 bradcast 給所有不共享 cache 的 CPU,cache invalidate broadcast 是很高的成本 (試想有上百個 CPU),如此 cache 也形同虛設,因為每次都在 invalidate
> 測驗 2 中 第 202 行為何要 `pos & queue->cell_mask` 而非 `pos % cell_count - 1` ?
因為 producer and consumer problem 的可存取空間會改變,所以 mask size 要當成一個結構體成為儲存,讓它可以變動,並用 bitwise and 來達到 mod 的效果
## zoanana990
> [fibdrv](https://hackmd.io/@zoanana990/linux2022-fibdrv)
移植原本在 usersapce 的大數運算到 Linux 核心模組時,遇到記憶體管理的問題。策略
1. 降低對 stdio 的使用和依賴:準備若干 test case,使用形如 `EXPECT(bn_init(1), 1);` 的程式碼來檢驗個別操作的正確性,不用肉眼比對十進位輸出
2. 使用巨集來包裝記憶體相關操作,例如 `MALLOC`,甚至加入對應的檢查和錯誤訊息
```c
#if define(__KERNEL__)
#define MALLOC(x) kmalloc(x)
#else
#define MALLOC(x) malloc(x)
#endif
```
3. 留意 `realloc` 的使用: realloc 若失敗,如何釋放記憶體
4. 善用 `printk` 和對應的 level,見 [Message logging with printk](https://www.kernel.org/doc/html/latest/core-api/printk-basics.html)
## cantfindagoodname
> [fibdrv](https://hackmd.io/@cantfindagoodname/linux2022-fibdrv)
[krealloc](https://www.kernel.org/doc/html/latest/core-api/mm-api.html#c.krealloc) 可能對執行時間帶來嚴重影響,改進策略:
1. 先行計算在給定的數值範圍,需要多大的記憶體空間,預先配置
2. 儘量使用預先配置的記憶體,並在 add 和 mul 檢查是否需要額外配置
3. 建立 square 作為 fast doubling 的加速操作,因為事先已知有效位數,可避免額外的比較
## Risheng1128
> [quiz3](https://hackmd.io/@Risheng/linux2022-quiz3)
- 測驗 `1`: 分析巨集函式 `GENMASK` 在 linux 核心原始碼的實作及考量
> [quiz2](https://hackmd.io/@Risheng/linux2022-quiz2)
- 測驗 `1`: 分析輸出的組合語言
- 測驗 `3`: 使用 gnu extension 改寫,並分析效能提升
## hankluo6
[quiz6](https://hackmd.io/@hankluo6/2022q1quiz6)
* 實作缺失
* 程式有時後會卡住
* Memory Leak
- [ ] Futex
* [Futex Scaling for Multi-core Systems](https://youtu.be/-8c47dHuGIY) / [slides](https://www.slideshare.net/davidlohr/futex-scaling-for-multicore-systems)
* [Linux 核心設計: 淺談同步機制](https://hackmd.io/@sysprog/linux-sync)
## arthurchang09
[quiz8](https://hackmd.io/@arthur-chang/linux2022-quiz8)
## blueskyson
- 面試被問到的問題:走訪檔案系統時,需要大量使用 file descriptor,但是在 Linux 系統中,同時可以 open 的 file descriptor 有限,請問如何利用有限的 file descriptor 來走訪深度很深的目錄。
## kdnvt
- thread sanitizer 說明頁面似乎有重複的句子。
- 閱讀 hazard pointer 論文理解複數 writer 的情況。
## Kevin-Shih
quiz11 的 `mpmc_init` 為何要檢查 queue 的記憶體地址是否對齊 16 B ?
https://en.wikipedia.org/wiki/False_sharing
ABA 問題和 mpmc
如何改進 mpmc 的測試
## SmallHanley
[quiz12](https://hackmd.io/@sysprog/linux2022-quiz12)
- `dequeue()` 中的 `batch_size` 是做什麼的?以及什麼時候會回傳 `SPSC_Q_EMPTY`?
- 如何設計測試程式,來判斷 `SPSC_Q_FULL`、`SPSC_Q_EMPTY` 等狀況?
## yaohwang99
[ktcp](https://hackmd.io/@yaohwang99/linux2022-ktcp)
如何確認 CMWQ 是否正確將任務分配至不同執行緒
CMWQ 如何選擇將任務派發至特定 CPU?
:::spoiler send/recv
```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;
/*
* TODO: during benchmarking, such printk() is useless and lead to worse
* result. Add a specific build flag for these printk() would be good.
*/
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);
return length;
}
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, size);
printk(MODULE_NAME ": send request = %s\n", buf);
return length;
}
```
:::
:::spoiler send/recv
```c
static int handle_message_from_client(int client, client_list_t **list)
{
int len;
char buf[BUF_SIZE];
memset(buf, 0, BUF_SIZE);
if ((len = recv(client, buf, BUF_SIZE, 0)) < 0)
server_err("Fail to receive", list);
if (len == 0) {
if (close(client) < 0)
server_err("Fail to close", list);
*list = delete_client(list, client);
printf("After fd=%d is closed, current numbers clients = %d\n", client,
size_list(*list));
} else {
printf("Client #%d :> %s", client, buf);
if (send(client, buf, BUF_SIZE, 0) < 0)
server_err("Fail to send", list);
}
return len;
}
```
:::
## ray90514
kecho 要如何處理大於 `BUF_SIZE` 的封包?
## steven1lung
[ktcp](https://hackmd.io/@steven1lung/linux2022-ktcp)
處理超過 buf_size 大小資料
## uduru0522
[Bottom-up Heapsort **比較**次數分析](https://hackmd.io/@Uduru0522/bottomup-heapsort-analyze)