# 2025q1 Homework5 (assessment) contributed by < `Hande1004` > ## 改進測驗題 [W2Q1](https://hackmd.io/@sysprog/linux2025-quiz2#%E6%B8%AC%E9%A9%97-1) 這題目標是使用 Linux 核心風格 List API 的簡化標頭檔 list.h 來開發快速排序程式碼。 為了把順序打亂來測試快速排序,用了 `random_shuffle_array()` 這個函式,而這之中負責打亂主要函式為 `getnum()` ,然而,這個函式以三個固定初始值的 `static uint16_t` 變數為種子,搭配固定的模數與乘數進行遞迴運算。這種設計屬於簡易的 deterministic pseudo-random number generator,其輸出完全由初始值決定,缺乏真正的隨機性來源。 因此,我決定改進這個部份,運用第一份作業(lab0)的 qtest.c 所寫到的 `os_random()` 函式來改寫。 ```c uint8_t os_random(void) { int seed = rand(); /* ASLR makes the address random */ uintptr_t x = (uintptr_t) &os_random ^ seed; struct timespec time; clock_gettime(CLOCK_MONOTONIC, &time); x ^= (uintptr_t) time.tv_sec; x ^= (uintptr_t) time.tv_nsec; return x; } ``` 接著我使用亂數品質分析工具 ENT,分別對 `getnum()` 與 `os_random()` 這兩個亂數產生函式進行測試。每個函式皆透過迴圈呼叫 100,000 次,每次產生一個 uint16_t 型態的亂數,總計輸出 200,000 bytes 的隨機資料,作為 ENT 測試的輸入樣本。 ```C int main() { srand(time(NULL)); for (int i = 0; i < 100000; i++) { uint16_t x = get_unsigned16(); fwrite(&x, sizeof(x), 1, stdout); } return 0; } ``` 然後得到輸出結果。 `getnum()`: ``` Entropy = 7.700204 bits per byte. Optimum compression would reduce the size of this 200000 byte file by 3 percent. Chi square distribution for 200000 samples is 76186.12, and randomly would exceed this value less than 0.01 percent of the times. Arithmetic mean value of data bytes is 121.7062 (127.5 = random). Monte Carlo value for Pi is 3.301473015 (error 5.09 percent). Serial correlation coefficient is 0.006997 (totally uncorrelated = 0.0). ``` `os_random()`: ``` Entropy = 7.999027 bits per byte. Optimum compression would reduce the size of this 200000 byte file by 0 percent. Chi square distribution for 200000 samples is 270.05, and randomly would exceed this value 24.73 percent of the times. Arithmetic mean value of data bytes is 127.2464 (127.5 = random). Monte Carlo value for Pi is 3.126991270 (error 0.46 percent). Serial correlation coefficient is 0.000427 (totally uncorrelated = 0.0). ``` 首先,`os_random()` 的熵為 7.999 bits/byte,幾乎達到理論最大值 8,代表每個 byte 的資訊含量非常接近理想的完全隨機。而 `getnum()` 僅達 7.70。 卡方分布也顯示了明顯差異:`os_random()` 的值為 270.05(約有 24.73% 機率自然超過此值),而 `getnum()` 高達 76186.12,遠遠偏離正常範圍,代表其 byte 值分布極不均勻。 ## 紀錄閱讀〈因為自動飲料機而延畢的那一年〉的啟發 就像作者一開始說,以為做飲料機很簡單,只要 > 落下杯子、移動杯子,加茶、加糖、加冰塊、加珍珠、再搖一搖、封模,一條龍一氣呵成的設備,操作者只要會按按鈕就行了。 然而直到作者與他們的團隊真的開始動手實作,才發現問題接踵而至,也才意識到自己其實什麼都不懂。看到這裡,也讓我想起之前看過的達克效應:正因為自身認知不足,才會以為生活中的許多例子都是理所當然。就像作者所提到的,當開始遇到許多機械問題時,他們才意識到自己對機械相關的知識幾乎是零,這也導致了許多問題的發生。 例如在冰塊的運輸過程中,因製造商與測量儀器精度不足,導致誤差累積,冰塊有時會卡住。但這些問題,往往必須等到製造商實際製作後,才能夠被測試及發現問題。接著又必須重新改進設計,再送回製造商製作,而這樣的來回過程就會耗費不少時間。 這堂課上,老師經常提醒我們:我們來這裡,就是為了解決真實世界的問題。然而,現實世界的問題,往往比我們想像的還要複雜許多——不是光靠想一想、說一說,事情就能順利完成。真正的挑戰,往往藏在那些繁瑣的細節之中。唯有不斷精進自己的技術與知識,讓 know-how 更加全面且深入,我們才能在面對真實世界的難題時迎刃而解。 在文中,作者遇到了一個很大的困難,就是分配冰塊的問題,這個問題可以看得出作者當時的無力感及絕望。 > 冰塊分配是個遠比我想像中困難的問題,就算液壓機可以凹出螺旋來,光是調整線徑和螺距就不知道要跑幾趟工廠。就算加工螺旋的問題解決了,後頭還有一坨拉庫的問題,諸如驅動螺旋的馬達挑選、符合食品安全等級的軸承、冰斗的形狀,我們甚至還沒解決冰塊黏在一起的問題。 我覺得,這些一次次的失敗,又或是好不容易想了一個辦法,卻發現這個方法依然不可行,這些種種真的會逐漸磨耗一個人的意志與鬥志。原本滿腔的熱血,經過多次的挫折後,也慢慢被澆熄了。換作是我,或許也會開始懷疑:「不如乾脆放棄吧,找個輕鬆一點的任務,做完就算,何必這樣折磨自己?」文中的作者,也曾經陷入這樣的心境: > 這個領域實在是太過廣博,現實如同真理般,給予和狂妄自負的傢伙相對應的絕望,對於沒有準備好的人毫不留情。我覺得自己像無頭蒼蠅一樣亂撞,做什麼都徒勞無功。我內心一直浮現「我是不是挑錯專案了」。之後還要延畢一學期, 然後又不會設計機構, 只能幫忙打雜。我問好友是不是該把這專案停掉, 先去做其他感覺比較能學習到東西的事,例如去其他公司實習之類的,他們沒辦法給出能說服我的建議。 然後故事的轉折是與 jserv 老師的聊聊後,讓作者重新找回繼續作的動力,老師說的一些話也讓我感觸很深。 > 不能現在就放棄,要是現在就放棄的話,你這輩子日後遇到這種等級的困難,就只會想逃避而已。 在我做這幾週作業的過程中,也曾無數次想過要放棄。因為許多作業的難度,是我過去從未遇過的挑戰,也涉及很多我從來沒學過的觀念與知識。每當卡關時,真的會懷疑自己到底能不能撐下去。 但我也告訴自己,如果現在一遇到困難就選擇逃避,那未來科技發展得越來越快,進入業界後遇到更大的挑戰時,難道也要用逃避來面對嗎?想到這裡,我就會咬著牙,逼自己再撐一下。正如老師常說的:「不懂不可恥,缺什麼就補什麼。」那些不會的知識,只要肯學,自然就會了。真正可惜的是還沒努力就選擇放棄。