大部分材料都來自於 Linux 核心設計/實作 (Linux Kernel Internals), 你所不知道的 C 語言
前篇:link
performance event
背景執行
item | description |
---|---|
I1 | first-level instruction cache |
D1 | first-level data cache |
L2 | second-level cache |
LL | last-level cache |
mr | read misses |
mw | write misses |
Bc | conditional branches executed |
Bcm | conditional branches mispredicted |
Bi | indirect branches executed |
Bim | indirect branches mispredicted |
C 語言標準並未定義 >>
右移為算術位移或邏輯位移
<<
則固定為邏輯位移
在 x86 Linux 上做一些小實驗:
其 memory contents 為:
使用 :
宣告要使用的 bit 數, unamed 0
會強制 alignment 。
when does compiler reorder my struct members?
為了避免需要 alignment 使得程式執行速度降低,所以編譯器在配置空間時常常會做 padding ,結構成員的順序也可能被移動
使用 #pragma pack
一類的預處理指令可以禁止編譯器做這些更動
alloc()
配置於 stack
mlockall()
:禁止所有 memory 被 swap out
Linux Torvalds 反對 variable length array 的使用
how to measure page fault?
copy-on-write
To read:
malloc()
manualattribute 相關 doc : https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html
cleanup :
The cleanup attribute runs a function when the variable goes out of scope. This attribute can only be applied to auto function scope variables; it may not be applied to parameters or variables with static storage duration. The function must take one parameter, a pointer to a type compatible with the variable. The return value of the function (if any) is ignored.
寫出適用於 CPU, GPU 的程式
malloc()
,需要 free()
不要使用 strncpy()
,以 strncpy()
代替, sstrncpy()
更高效且安全。
assert()
issues an error at execution-timestatic_assert()
issues an error at compile-time為什麼 container_of()
巨集需要宣告 pmember
,不能直接使用 (char *) ptr - offset
嗎?
為了避免 side effect
To read:
https://www.slideshare.net/jserv/how-a-compiler-works-gnu-toolchain
每個被 assign 的變數只會出現一次
跨平台多執行緒 API : OpenMP, C++ AMP
編譯器難以 inline 外部函式,除非有 link time optimization 。
To read:
Let out
be the name of output file.
使用 diagram 來幫助了解物件之間的互動關係
To read:
針對 glibc 的解說
設定 LD_PRELOAD 可以讓 glibc 的 dynamic linker 在 load 和 relocate libc.so 之前載入我們撰寫的動態連結函式庫。
ld.so
, ld-linux.so
To read:
Macro with ({
})
is called statement expression.
process 與 thread 差異取決於作業系統如何看待
To read:
Sequecedbefore 是種對同一個執行緒下,求值順序關係的描述。
Sequenced before 在數學上是一種 asymmetric 和 transitive 的 relation 。
如果每個處理器都有自己的 write buffer 並對 program 進行最佳化,就很可能違反 sequential consistency 。
要求「看起來」的結果
To read:
In Unix enviroment, a thread
Threads reading and writing to the same memory locations is possible, and therefore requires explicit synchronization by the programmer.
<pthread.h>
compile with gcc argument -pthread
Some APIs :
pthread_create()
pthread_exit()
pthread_cancel()
thread
: An unique identifier
attr
: attribute, we may specify NULL
for default values
start_routine
: will be executed once the thread is created
arg
: single argument that may be passed to start_routine
There are several ways in which a thread may be terminated :
pthread_exit()
.pthread_cancel()
.main()
finishes.By having main()
explicitly call pthread_exit()
as the last thing it does, main()
will block and be kept alive to support the threads it created until they are done.
When a thread is created, one of its attributes defines whether it is joinable or detached. Only threads that are created as joinable can be joined. If a thread is created as detached, it can never be joined.
The pthread_detach()
routine can be used to explicitly detach a thread even though it was created as joinable.
For portability, create explicitly as joinable or detachable.
PTHREAD_MUTEX_INITIALIZER
pthread_mutex_init()
pthread_mutex_unlock()
pthread_mutex_destroy()
To read:
user-mode 的程式藉由 system call 來向 os 要資源
strace
追蹤 system callltrace
追蹤 library callscheduling 的時候把相關的 process 視為一個 group 一起排
測量 scheduling 的成本:
RB tree 在 worst case 的表現優於 AVL tree
kernel 中會有 disable preemption 的區域
在 kernel 中計時的方法本質上就是一個 counter,有一個固定的頻率,週期乘以計數器的差值就可以取到時間。
用 struct clocksource 來抽象化 hardware counter
POSIX clocks:
在沒有 hardware counter 的系統上引用 GPS,jiffies,雖然不會有 nanosecond resolution,但勉強能用。
抽象成 struct clock_event_device
kernel 藉著 HZ
變數來算時間,而 tickless kernel 引進 NO_HZ 的全新機制。
The tick rate is a periodic interrupt, HZ
.
The value of HZ
is architecture dependent. 該值在編譯時期就要決定。
larger HZ
的優點:
缺點:
fire the timer 觸發計時器
越精準的的 timer 越耗電,因此系統可能提供很多組 timer,有些 resolution 偏低但是可以省電。
系統休眠的時候改用 tickless 機制來省電
tickless 需要使用 RCU
cputime counting:
utime
for user-spacestime
for kernel-space
<linux/jiffies.h>
The global variable jiffies holds the number of ticks that have occured since the system booted. On boot, the kernel initializes the variable to zero, and it is incremented by one during each timer interrupt.
jiffies
在 32-bit 上是 u32,在 64-bit 上是 u64。
每秒有 HZ
個 timer interrupt,因此 system uptime 就是 jiffies
HZ
(second)。
基本上 (在一般的 HZ
value 之下) 64-bit 上的 jiffies
不會在人類的生命時長裡 overflow。
變數 xtime
紀錄現在的時間和日期
timer interrupt 分成:
jiffies_64
by onextime
系統初始化時所使用的 mm 機制
分成一些 大小的記憶體區塊,需要時直接去取用。
buddy system 有 fragmentation 的問題
使用 list 來管理 pages,分成 3 條 lists
slab 會一次拿很多 page,然後把 page 切分成很多小塊等著被 allocate。
在多 CPU、NUMA 的情境非常劣勢
ABI:application binary interface
VFS:virtual file system
FHS:filesystem hierachy
user-space 可以藉由修改 /proc
pseudo file system 來在執行時期變更 kernel 行為
..