sysprog
2019
2019spring
contributed by < czvkcui
>
認真看作業要求,除了提及如何逐步達到要求,還需要進行:
還未達成符合預期目標,請繼續付出!
q_new
,q_free
,q_insert_head
,q_insert_tail
,q_remove_head
,q_size
,q_reverse
implement
size保存linked list 的長度
q_new 初始化queue_t
結構
利用goto
來統一處理例外狀況
we have 2 hooks inside our scripts:
git commit
commandinit_cmd和console_init會向console註冊所使用的command
main
->run_console
->cmd_select
->interpret_cmd
->interpret_cmda
cmd_list
是一個link list,它保存了queue_init
和init_cmd
所註冊的command。透過循序搜尋找到符合的cmd,然後執行對應的函式(next_cmd->operation)。
Q:Why limit_bytes = mblimit<<20 ?
A:mblimit 作為判斷malloc有無超出上限,mblimit<<20
代表最高可以使用的大小(KB),在本例中0
<<20還是為0(mblimit
預設為0
表示無上限)
Q:Why we need (void)
before delta_time(timep) ?
A:某些編譯器可能會警告使用者沒有處理返回值,加上(void)
來處理返回值(轉形成void),但是像是printf
等常用的function可以在宣告時加上__attribute__(noreturn)
來避免。
在gcc中
-Wall
預設會開啟Wunused-result
,不過在我的平台上(gcc (Ubuntu 7.3.0-16ubuntu3) 7.3.0
),刪除(void)
和加上-Wunused-result
都沒有效果。此外也可以在function宣告加上__attribute__((warn_unused_result))
強迫警告使用者處理返回值。
獲取資源的使用情形
declaration:
int getrusage(int who, struct rusage *usage);
usage接受一個參數負責返回結果,而who則有以下參數
queue.c
因為有include harness.h
因此呼叫的malloc
和free
為test_malloc
和test_free
。
struct of block_ele_t
payload[0]是C99後引入的語法,可以允許使用者在runtime時才決定該array大小。
size是是真正要給使用者使用的空間大小(bytes),加上block_ele_t的大小,sizeof(size_t)則是儲存footer的空間。在test_malloc
中,block_ele_t會依序填上MAGICHEADER
、size
、 FOOTER
、payload
,接著將next指向link list的開頭(allcated則指向新的new block,舊的prev指標指向新的block),再由allocated_count++
後完成記憶體分配。test_free
會檢查要被釋放的block的MAGICHEADER
和MAGICFOOTER
。當payload存取的資料超過payload的大小時會覆蓋自己的MAGICFOOTER
,MAGICHEADER
則可以檢查自己的block是否被別人所覆蓋[1]。最後test_free
將block移出double link list,allocated_count--
釋放block。
jmp_read
的type是volatile
,在參考from C 語言 setjmp 與 longjmp 函數用法教學後得知:
-O
)只有 register
宣告的變數會改變(not change:volatile
.global
,static
,local
)
-O
option: register
,local
宣告的變數值均會改變sigsetjmp
,siglongjmp
:
setjmp
和longjmp
一樣都是nonlocal jmpsetjmp
和longjmp
並不會在jump儲存當前的signal mask當exception觸發(SIGSEGV,SIGALRM),jmp_rady
會被trigger成true,而進行setlongjmp
至上一個exception_setup
位置(if (sigsetjmp(env, 1))
),印出錯誤訊息後返回。
exception_cancel
:清除'jmp_ready'和error_message,若是超時則會觸發alarm。
根據exception_setup
和exception_cancel
可以得知
queue_init
會使qtest在初始化時註冊SIGSEGV
和SIGALRM
,當中斷發生時OS會通知signal handler做對應的處理,在本例中SIGSEGV
發生時會交由sigsegvhandler
,而SIGALARM
由sigalrmhandler
處理,兩者都是印出錯誤訊息後,呼叫trigger_exception
。
修改driver.py
以 process pool來執行:
Performance counter stats for 'python scripts/driver.py'(with process pool):
1276.391265 task-clock (msec) # 1.327 CPUs utilized
842 context-switches # 0.660 K/sec
58 cpu-migrations # 0.045 K/sec
135,961 page-faults # 0.107 M/sec
3,941,655,638 cycles # 3.088 GHz
6,034,081,563 instructions # 1.53 insn per cycle
1,167,962,182 branches # 915.050 M/sec
2,832,393 branch-misses # 0.24% of all branches
0.961677493 seconds time elapsed
Performance counter stats for 'python scripts/driver.py':
1007.687420 task-clock (msec) # 0.797 CPUs utilized
803 context-switches # 0.797 K/sec
12 cpu-migrations # 0.012 K/sec
131,010 page-faults # 0.130 M/sec
3,107,377,907 cycles # 3.084 GHz
5,928,785,192 instructions # 1.91 insn per cycle
1,146,581,106 branches # 1137.834 M/sec
2,129,417 branch-misses # 0.19% of all branches
1.264532373 seconds time elapsed
In [2]: (1.264532373-0.961677493)/1.264532373 * 100
Out[2]: 23.949950706402355
在用perf record分析時,發現有些部份可能可以交由編譯器最佳化,例如每次malloc都會被呼叫但是回傳值都是一樣的fail_allocation