강좌 & 팁
커널모듈을 테스트하는 중에는 많은 printk를 사용하게 된다. 또한 모듈이 제어하는 디바이스에 이상이 생길 때
동일한 많는 수의 (커널)메시지를 발생하게 되어 운영체제에 좋지 않는 영향을 미치는 경우가 서버운영중에 종종 나타나게 된다.
이러한 경우에 대비하기 위해 모듈프로그래머가 할 수 있는 일은 불필요한 많는 수의 printk를 생산해 내지 않는 것이다.
이러한 일을 돕기 위해 linux커널에서 제공하는 것이 printk_ratelimit()라는 커널API이다.
이것은 간단히 말하면, 현 시점에서 최근(msec)에 printk가 호출되었는지 아닌지를 판별하는 함수이다.
함수와 함께 전달해야 할 파라메터는 없으며, 다음과 같이 사용할 수 있다.
for (i=0; i<100; i++) {
if (printk_reatlimit()) {
printk("kernel message-%d\n", i);
}
}
그러면, 얼마만큼의 printk를 허용할 것인가를 정해야 할 것이다. 또한 printk()가 영원히 차단되면 당연히 안 되기 때문에
어느 정도의 시간이 지나면 printk()를 다시 허용할 것인지를 정해야 할 것이다. 이러한 기능을 하는 것인 바로 /proc/sys/kernel밑에
다음 2개의 파일이다.
1) printk_ratelimit_burst: 한꺼번에 허용되는 printk호출 횟수, 'struct ratelimit_state'의 burst필드값
2) printk_ratelimit: 차단된 후 다시 허용되기 까지의 시간간격(초), 'struct ratelimit_state'의 interval필드값
이 함수 printk_ratelimit()와 관련되어 있는 ___ratelimt()를 살펴보자.
int ___ratelimit(struct ratelimit_state *rs, const char *func);
rs는 interval과 burst값을 가지고 있는 구조체이다. func는 함수 printk_ratelimit()를 호출한 곳에 해당하는 함수이름이다.
커널의 jiffies값이 rs->begin으로부터 rs->interval사이에 있다면 printk는 차단된다.
현재 시각(jiffies)이 rs에 지정된 시간간격을 지나면(begin,interval) printk를 다시 허용된다.
int ___ratelimit(struct ratelimit_state *rs, const char *func) {
.....
if (time_is_before_jiffies(rs->begin + rs->interval)) { // printk금지를 해제
// # of missed-messages 리포팅
printk(KERN_WARNING "%s: %d callbacks suppressed\n", func, rs->missed);
// rs구조체를 초기화
rs->begin = 0;
rs->printed = 0;
rs->missed = 0;
return true;
}if (rs->burst > rs->printed) { // printk수가 burst값보다 작다면 ...
rs->printed++; // 현재까지 누적된 printk수가 rs->printed에 저장되어 있다.
ret = true; // printk호출가능
} else {
// printk호출가능하지 않음
rs->missed++; // printk를 호출한다면, 메시지 miss될 것임을 의미함
ret = false;
}
.....return ret;
}
결론적으로 printk_ratelimit()를 사용한다면, 시간간격(interval)내에서의 printk호출을 burst개로 제한시킬 수 있다.