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