delayacct_init()
kernel/delayacct.c
void delayacct_init(void) { delayacct_cache = KMEM_CACHE(task_delay_info, SLAB_PANIC); delayacct_tsk_init(&init_task); }
CONFIG_TASK_DELAY_ACCT 커널 옵션을 사용하는 경우 task에 대한 각종 지연 stat을 얻을 수 있다.
- cpu, 동기 블록 입출력 완료 및 페이지 스와핑과 같은 시스템 자원을 기다리는 작업에 소요되는 시간에 대한 정보를 수집합니다.
- “nodelayacct” 커널 파라메터를 사용하는 경우 delay accounting 기능을 disable한다.
__delayacct_tsk_init()
kernel/delayacct.c
void __delayacct_tsk_init(struct task_struct *tsk) { tsk->delays = kmem_cache_zalloc(delayacct_cache, GFP_KERNEL); if (tsk->delays) spin_lock_init(&tsk->delays->lock); }
요청 태스크의 delays 멤버에 delayacct_cache 구조체를 할당받은 후 초기화한다.
delayacct_setup_disable()
kernel/delayacct.c
int delayacct_on __read_mostly = 1; /* Delay accounting turned on/off */ EXPORT_SYMBOL_GPL(delayacct_on); struct kmem_cache *delayacct_cache; static int __init delayacct_setup_disable(char *str) { delayacct_on = 0; return 1; } __setup("nodelayacct", delayacct_setup_disable);
“nodelayacct” 커널 파라메터를 사용하는 경우 delay accounting 기능을 disable한다.
Per-task Delay Accounting
delayacct_freepages_start()
include/linux/delayacct.h
static inline void delayacct_freepages_start(void) { if (current->delays) __delayacct_freepages_start(); }
태스크의 delay accounting에 사용하기 위해 현재 시작 clock을 기록한다.
__delayacct_blkio_start()
kernel/delayacct.c
void __delayacct_freepages_start(void) { current->delays->freepages_start = ktime_get_ns(); }
태스크의 delay accounting에 사용하기 위해 현재 시작 clock을 기록한다.
delayacct_freepages_end()
include/linux/delayacct.h
static inline void delayacct_freepages_end(void) { if (current->delays) __delayacct_freepages_end(); }
태스크의 delay accounting에 사용하기 위해 시작 clock에서 현재 clock을 빼서 기록한다.
__delayacct_freepages_end()
kernel/delayacct.c
void __delayacct_freepages_end(void) { delayacct_end(¤t->delays->freepages_start, ¤t->delays->freepages_delay, ¤t->delays->freepages_count); }
태스크의 delay accounting에 사용하기 위해 현재 clock에서 freepages_start clock을 빼서 freepages_delay에 delay time을 추가하고 freepages_count를 증가시킨다.
delayacct_end()
kernel/delayacct.c
/* * Finish delay accounting for a statistic using its timestamps (@start), * accumalator (@total) and @count */ static void delayacct_end(u64 *start, u64 *total, u32 *count) { s64 ns = ktime_get_ns() - *start; unsigned long flags; if (ns > 0) { spin_lock_irqsave(¤t->delays->lock, flags); *total += ns; (*count)++; spin_unlock_irqrestore(¤t->delays->lock, flags); } }
delay accounting에 사용하기 위해 현재 clock에서 인수로 전달받은 start clock을 빼서 total에 추가 하고 count를 증가시킨다.
getdelays 유틸리티 빌드 및 사용
- Documentation/accounting/getdelay.c를 컴파일하여 사용한다.
- gcc -I/usr/src/linux/include getdelays.c -o getdelays
./getdelays getdelays [-dilv] [-w logfile] [-r bufsize] [-m cpumask] [-t tgid] [-p pid] -d: print delayacct stats -i: print IO accounting (works only with -p) -l: listen forever -v: debug on -C: container path
참고
- Documentation/accounting/delay-accounting.txt | kernel.org
- Per-task delay accounting | LWN.net