SP 靈異事件表

這邊彙整了各種曾經遇過的奇怪問題,雖然有些東西不能算是靈異事件就是了。

HW0

make

all: <要編譯的檔案名稱> 
<編譯指令>
clean:
rm -rf <編譯完的執行檔> <其他要刪的東西>

作業應該只會需要這些。

HW1 - connection and IO multiplexing

小心 \r\n

有些助教的測資是用 \r\n 換行而不是 \n,在 handle read 的時候要特別把它處理掉。

自己不會被自己的 lock 擋住

如果一個 process 有兩個 client,而兩個 client 都想要去存取一個檔案,你會發現即使有 lock 也無法阻止兩人同時對同個區域讀寫,
因為同一個 process 的 lock 不會擋自己。

沒有按下 enter 卻送出訊息的 case

當初助教有叫我們處理這個 case,但大家似乎都沒有重現出這個 case,所以也不知道怎麼測試。
後來我是在用自家電腦當 client,工作站上的程式當 server 的時候重現了這個 case。

IO multiplexing

大致雛型像這樣:

while true:
do select or poll
for i in client:
process client[i]

要注意 process client 的時候不要用會 block 的函式。
這樣就可以同步處理多個 client 了。
雖然很多人用 poll,但我個人私心覺得用 select 更簡潔一點就是了。

accept connection 的時機

因為 accept 會 block 直到有 connection,但通常我們不希望這樣。
在上面 select 的時候可以把 server listen fd 也丟進去,如果它還留在 select 的話就表示有新的 connection 進來。

busy wait

沒什麼特別的,只是我 select 的 timeout 設 0.01s 結果被助教判定成 busy wait 了。

字串⇔數字

字串轉數字可以用 atoi
數字轉字串可以用 sprintf

HW2 - fork, pipe, and fifo

handle read

如果 read 的來源是 stdin 的話,要用 getline 或 fgets 之類的讀,如果是其他東西的話要用 read 讀。

read return 0 但 errno = 0

大概是因為讀到 EOF 吧。

read 到奇怪的文字

因為 read 不會自動在字串尾部補 \0,所以在 read 之前要先把 buffer 初始化成 0。

strtok 內包 strtok

strtok 沒辦法用巢狀結構,所以必要的時候必須自己寫一個函式取代它。

pipe 內的訊息跑到奇怪的地方、read / write 跳出 wrong fd

我自己遇到兩次這個問題,第一次找半天找不到 bug 就乾脆整個重寫一次,結果還是遇到了這個問題。
後來是暴力列出所有時候誰開了幾號 fd,誰關了幾號 fd 慢慢手動驗證才找出問題。

下面是我當初出問題的程式:

dup2(ptc[READ],PARENT_READ_FD);
dup2(ctp[WRITE],PARENT_WRITE_FD);

if(ptc[READ]!=PARENT_READ_FD){
close(ptc[READ]);
}
if(ctp[WRITE]!=PARENT_WRITE_FD){
close(ctp[WRITE]);
}

後來發現,我漏掉了 ptc[READ]==PARENT_WRITE_FD 和 ctp[WRITE]==PARENT_READ_FD 的 case。

另一個可能是在 exec 的時候沒有先把多餘的 fd 關掉導致出現了不該存在的訊息管道。

HW4

常數太大

我一開始的程式執行時間大概是其他人的 4~5 倍,後來總算想辦法把常數壓下來了,不然我應該會被判 TLE。
大致上就是減少呼叫函式,以及儘可能地簡化 signal 和 lock 邏輯吧。

memory leak

這個我真的不知道發生什麼事了。
我自己覺得該 free 的都 free 了,也用 detach 處理 thread,但還是被扣 memory leak。
我看大部分人都是約 10 萬個 unfree,但我是 17 個 unfree