contributed by < grant7163
>
sysprog2019_q1
首先判斷 cirbuf 是否已滿,若還沒滿則將 data 複製到 cirbuf tail 中並更新 tail 的位置,最後在檢查 tail 是否有超出 cirbuf 的記憶體區段,若超出 cirbuf 的記憶體區段則將 tail 取餘數(tail % cirbuf size)。
首先判斷 cirbuf 是否為空,若不為空則將 cirbuf head 中的資料取出並更新 head 的位置。
ps : 藍色圈圈為 head, 橘色圈圈為 tail
查閱 linux man page 了解相關說明。
$ man mkstemp
The function generates a unique temporary filename from template, creates and opens the file, and returns an open file descriptor for the file.
The last six characters of template must be "XXXXXX" and these are replaced with a string that makes the filename unique. Since it will be modified, template must not be a string constant, but should be declared as a character array.
$ man 2 unlink
unlink() deletes a name from the filesystem. If that name was the last link to a file and no processes have the file open, the file is deleted and the space it was using is made available for reuse.
If the name was the last link to a file but any processes still have the file open, the file will remain in existence until the last file descriptor referring to it is closed.
If the name referred to a symbolic link, the link is removed.
$ man 2 ftruncate
If the file previously was larger than this size, the extra data is lost. If the file previously was shorter, it is extended, and the extended part reads as null bytes ('\0').
If the size changed, then the st_ctime and st_mtime fields (respectively, time of last status change and time of last modification; see inode(7)) for the file are updated, and the set-user-ID and set-group-ID mode bits may be cleared.
在 cirbuf 目錄下輸入 make 後會自動執行測試程式並將訊息顯示在終端機上,可以看到會額外產生一個 main.c,不難發現這就是剛剛在執行的測試程式。
從 makefile 中觀察 main.c 是透過一個 shell script 的腳本(gentest.sh
) 產生的。
將檔案指定為 command line 的第一個 arguments(在此為 test-cirbuf.c),接著使用 sed 命令編輯文字。
先將 test-cirbuf.c 中所有開頭為 void Test 的字串列出來,接著將 ( 之後的字串替換為 (CuTest*);
並將字串開頭替換為 extern。
sed -e 's/^void //'
: 將 void 取代為 空白
參考 3.3 The s Command
*
: 匹配前面的(左鄰)字元有 0 個以上
.
: 匹配任何字元
^
: 表達式的開頭
$
: 表達式的結尾
參考 5.3 Overview of basic regular expression syntax
在 main.c 中,建立一個 suite 來管理整個測試資料,透過 SUITE_ADD_TEST 這樣的 macro 將要測試的函式加入到 suite 中的 list。
以 TestCirbuf_set_size_with_init() 函式為例 :
建立一個 CuTest 的變數並將 TestCirbuf_set_size_with_init 指派給該變數,後續就可以透過這個變數來呼叫該函式(callback function)。
接著從 testSuite 中一一執行先前所加入的 testCase。
在第 16 行的 tc->function
實際是執行先前指派的TestCirbuf_set_size_with_init
。
故意先將 CuAssertTrue(tc, 65536u == cirbuf_size(&cb));
的大小改為不相等,使其方便觀察 CuAssertTrue 函式的整個作用。
當 cond 為 1 時就直接 return 結束一個測試項目,否的話則紀錄錯誤資訊。
將 assert failed
, __FILE__
, __LINE__
加入到該測試項目的 tc->message ,接著使用 longjmp 回到當初呼叫 setjmp() 的地方。
$ man memmove
The memmove() function copies n bytes from memory area src to memory area dest. The memory areas may overlap: copying takes place as though the bytes in src are first copied into a temporary array that does not overlap src or dest, and the bytes are then copied from the temporary array to dest.
最後藉由 CuStringAppendFormat() 函式顯示統計的結果。
在 unit-test.c 中針對當有配置記憶體空間失敗時直接回傳 NULL 並印出錯誤訊息,接著不要讓該測試項目加入到測試 list 中。
儘管已有 12 個 test case,但涵蓋層面仍不夠廣泛,請指出現有實作的缺陷並著手改善; (提示: 數值範圍及多個 PAGE_SIZE 的空間)
學習 Using black magic to make a fast circular buffer,指出 fast circular buffer 實作的技巧,並分析 cirbuf 的效能,並逐步量化及改善效率;
$ man 2 mmap
mmap() creates a new mapping in the virtual address space of the calling process.