contributed by < leewei05
>
memchr_opt 初步理解為以下:
注意用詞:
尊重資訊科技前輩的篳路藍縷,儘量使用傳統詞彙。
jserv
首先會判斷帶入的字串長度是否比 8 個位元組還要長,如果比 8 個位元組還短即比對各個位元組 (byte) 搜尋指定的 char。如果比字串比 8 個位元組還要長,那就會進入 if (!TOO_SMALL(length))
的判斷式。
與其一個位元組接著一個位元組比對,memchr 會根據 unsigned char d
(欲搜尋的字元) 製作一個 8 個位元組的 bytemask。
執行結果如下:
一開始很快就 parse 出 .
,但加了另外兩個 case 發現都會回傳 NULL。透過 gdb 檢查之後發現這行寫錯了。原本是要位移一個 pointer to long,但一開始寫的版本是取回一個位元組,所以才會出錯。也因為為了熟悉 gdb 的關係,花了不少時間,但學會使用 gdb 除錯真的節省不少時間以及排除用感覺寫程式的壞習慣。
首先從核心模組的 init function 開始看起。查閱 Linux Kernel 原始碼,dont_trace_init
基本上就是建立一個 work queue,並且設定 work queue 的延遲時間(1 Jiffy)。
exit function 則是停止 work queue 的 routine 並清除先前定義的 work queue。
除了 periodic_routine
以外需要實作,其他四個函式分別為:
kill_task
: 刪除 Kernel space 的行程is_tracer
: 判斷行程是否有追蹤其他行程kill_tracee
: 刪除所有 tracer 追蹤的行程check
: 檢查所有的行程的 ptraced,也就是追蹤的行程。如果 is_tracer
返回 true,則刪除所有追蹤行程以及該行程。首先,likely
巨集是由 gcc extension __builtin_expect
組成。此用途是可提示編譯器產生對 branch predictor 友善的程式碼,因為工程師可以透過 __builtin_expect
來告知編譯器 !!(x) == 1
的機率很大,也就是 x 很可能為 1。!!
是確保 !!(x)
的結果一定為 0 或是 1。
6.5.3.3 Unary arithmetic operators
The result of the logical negation operator ! is 0 if the value of its operand compares
unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int.
The expression !E is equivalent to (0==E)
什麼時候需要會需要執行 check()
? A: 掛載核心模組的時候。
可以使用 init function 所定義的 loaded = true;
,因為大部分的時間 loaded == true
。
測試程式碼
當一個行程追蹤了另一個行程,被追蹤的行程 (tracee) 需要成為追蹤行程 (tracer) 的子行程,tracer 擁有 tracee 的控制權,包括設定 break point,檢視 tracee 的記憶體位址,攔截系統呼叫等等。GDB 即是透過 ptrace 實現上述的功能。
Ptrace 的限制
參考文件
Ptrace manual
Intercepting and Emulating Linux System Calls with Ptrace
Ptrace, Utrace, Uprobes: Lightweight, Dynamic Tracing of User Apps