Debugging the kernel using ftrace — Part 2
원문 : http://lwn.net/Articles/366796
저자 : Steven Rostedt
일자 : December 22, 2009
Ftrace는 리눅스 커널 문제를 추적하는데 도움이 되는 다양한 기능을 가지고 있다.
The Ftrace tracing utility has many different features that will assist in tracking down Linux kernel problems.
이전 글에서는 Ftrace 설정과 function tracer, function graph tracer를 사용하는 방법, 그리고 trace_printk()를 사용하는 방법, trace에 기록하는것을 user space에서 멈추는 방법을 다뤘다.
The previous article discussed setting up Ftrace, using the function and function graph tracers, using trace_printk(), and a simple way to stop the recording of a trace from user space.
이번 회에서는 user space에서 ftrace와 상호작용하는 방법, trace를 빠르게 멈추는 방법, crash를 디버깅하는 방법, 어떤 커널 함수가 제일 스택을 많이 차지하고 있는지(stack hogs)를 찾는 방법을 다룰 것이다.
This installment will touch on how user space can interact with Ftrace, faster ways of stopping the trace, debugging a crash, and finding what kernel functions are the biggest stack hogs.
Trace 표시
커널 안에서 일어나는 일을 살펴보면 시스템이 어떻게 동작하는지에 대해 더 잘 알게 해준다. 하지만 때때로 user space에서 어떤 일이 일어나고 있고 커널 안에서는 어떤 일이 일어나고 있는지 사이에서 조정할 필요가 있다.
Seeing what happens inside the kernel gives the user a better understanding of how their system works. But sometimes there needs to be coordination between what is happening in user space and what is happening inside the kernel.
trace에서 보이는 타임스탬프는 trace안에서 어떤 일이 발생했는지를 상대적인 시간으로 보여준다, 하지만 walltime과 일치하지 않는다.
The timestamps that are shown in the traces are all relative to what is happening within the trace, but they do not correspond well with wall time.
user space와 kernel space 사이의 action을 동기화하기 위해, trace_marker 파일이 제공된다. 이 파일은 user space에서 링 버퍼에 데이터를 쓸 수 있는 방법을 제공한다.
To help synchronize between the actions in user space and kernel space, the trace_marker file was created. It provides a way to write into the Ftrace ring buffer from user space.
이 marker는 특별한 이벤트가 발생한 위치를 표시하기 위해 trace에 나타난다.
This marker will then appear in the trace to give a location in the trace of where a specific event occurred.
[tracing]# echo hello world > trace_marker
[tracing]# cat trace
# tracer: nop
#
# TASK-PID CPU# TIMESTAMP FUNCTION
# | | | | |
<...>-3718 [001] 5546.183420: 0: hello world
<…>는 마킹한 태스크의 이름을 표시하는데 아직 기록되지 않는다. 추후 릴리즈에서 이 문제가 수정될 것이다.
The <…> indicates that the name of the task that wrote the marker was not recorded. Future releases may fix this.
프로그램에서 trace를 시작,정지,기록하기
만약 어플리케이션의 source를 가지고 있다면 tracing_on과 trace_marker 파일은 어플리케이션의 행동을 trace하는데 매우 잘 동작한다.
The tracing_on and trace_marker files work very well to trace the activities of an application if the source of the application is available.
만약 어플리케이션 안에 문제가 있고 어플리케이션의 특정 위치에서 커널 안은 어떤 일이 발생했는지 알아야 하는 경우에는 두 파일이 유용하다.
If there is a problem within the application and you need to find out what is happening inside the kernel at a particular location of the application, these two files come in handy.
어플리케이션의 시작점에서, 준비된 fd를 얻기 위해 이 파일들을 열 수 있다.
At the start of the application, you can open these files to have the file descriptors ready:
int trace_fd = -1;
int marker_fd = -1;
int main(int argc, char *argv)
{
char *debugfs;
char path[256];
[...]
debugfs = find_debugfs();
if (debugfs) {
strcpy(path, debugfs);
strcat(path,"/tracing/tracing_on");
trace_fd = open(path, O_WRONLY);
if (trace_fd >= 0)
write(trace_fd, "1", 1);
strcpy(path, debugfs);
strcat(path,"/tracing/trace_marker");
marker_fd = open(path, O_WRONLY);
그리고 코드 안의 중요한 위치에서, 어플리케이션이 현재 어떤 상황인지를 보기 위해 marker를 둘 수 있다.
Then, at some critical location in the code, markers can be placed to show where the application currently is:
if (marker_fd >= 0)
write(marker_fd, "In critical area\n", 17);
if (critical_function() < 0) {
/* we failed! */
if (trace_fd >= 0)
write(trace_fd, "0", 1);
}
예제에서 보듯이, 먼저 find_debugfs()를 호출해야 한다. debugfs를 마운트하는 알맞은 위치는 /sys/kernel/debug이지만 강건한 툴은 debugfs가 거기에 마운트되었다는 것에 의존하면 안된다.
In looking at the example, first you see a function called “find_debugfs()”. The proper location to mount the debug file system is at /sys/kernel/debug but a robust tool should not depend on the debug file system being mounted there.
find_debugfs()의 한 예는 여기에 있다. 커널에 tracing기능이 활성화되어있든 아니든, 이 코드의 동작을 허용하기 위해 파일 디스크립터는 -1로 초기화된다.
An example offind_debugfs() is located here. The file descriptors are initialized to -1 to allow this code to work both with and without a tracing enabled kernel.
문제가 포착되면, trace_fd 파일 디스크립터에 “0”이 쓰여지면서 tracing이 정지한다.
When the problem is detected, writing the ASCII character “0″ into the trace_fd file descriptor stops tracing.
part 1에서 얘기했듯이, Ftrace 링 버퍼로의 기록을 비활성화할 뿐이며, tracer는 여전히 오버헤드를 유발하고 있다.
As discussed in part 1, this only disables the recording into the Ftrace ring buffer, but the tracers are still incurring overhead.
위 초기화 코드를 사용할 때, tracer는 overwrite mode에서 동작하고 있기 때문에 tracing은 어플리케이션의 시작점에서부터 활성화된다. trace 버퍼가 가득 채워지면 오래된 데이터를 제거하고 새로운 데이터로 교체한다.
When using the initialization code above, tracing will be enabled at the beginning of the application because the tracer runs in overwrite mode. That is, when the trace buffer fills up, it will remove the old data and replace it with the new.
문제가 발생했을 때에는 최근의 trace 정보만 의미가 있기 때문에 일반적인 어플리케이션의 수행도중에는 tracing을 멈춘 다음 시작할 필요가 없다.
Since only the most recent trace information is relevant when the problem occurs there is no need to stop and start the tracing during the normal running of the application.
tracer는 문제가 포착되었을 때만 오직 비활성화될 필요가 있다. 따라서 trace는 에러가 유발되기까지의 히스토리를 가지고 있을것이다.
The tracer only needs to be disabled when the problem is detected so the trace will have the history of what led up to the error.
만약 interval tracing이 어플리케이션 내에서 필요하다면, tracing을 활성화하기 위해 trace_fd에 “1”를 쓸 수 있다.
If interval tracing is needed within the application, it can write an ASCII “1″ into the trace_fd to enable the tracing.
여기에 simple_trace.c라는 간단한 프로그램 예제가 있다. 이 프로그램은 위에서 기술한 초기화 과정을 사용한다.
Here is an example of a simple program called simple_trace.c that uses the initialization process described above:
req.tv_sec = 0;
req.tv_nsec = 1000;
write(marker_fd, "before nano\n", 12);
nanosleep(&req, NULL);
write(marker_fd, "after nano\n", 11);
write(trace_fd, "0", 1);
오직 예제를 보여주는 목적으로만 만든 간단한 프로그램이기 때문에 에러체킹 코드는 넣지 않았다.(No error checking was added due to this being a simple program for example purposes only.)
이 간단한 프로그램을 trace하는 절차이다.
Here is the process to trace this simple program:
[tracing]# echo 0 > tracing_on
[tracing]# echo function_graph > current_tracer
[tracing]# ~/simple_trace
[tracing]# cat trace
프로그램이 시작되면 활성화하기 때문에 첫 번째 라인에서는 tracing을 비활성화한다. 다음으로 function graph tracer를 선택한다.
The first line disables tracing because the program will enable it at start up. Next the function graph tracer is selected.
프로그램이 실행되면, 아래와 같은 trace가 결과로 나온다. output은 […] 으로 생략되어 아래보다 조금 더 장황할 수 있다.
The program is executed, which results in the following trace. Note that the output can be a little verbose so much of it has been cut and replaced with […]:
[...]
0) | __kmalloc() {
0) 0.528 us | get_slab();
0) 2.271 us | }
0) | /* before nano */
0) | kfree() {
0) 0.475 us | __phys_addr();
0) 2.062 us |
0) 0.608 us | inotify_inode_queue_event();
0) 0.485 us | __fsnotify_parent();
[...]
1) 0.523 us | _spin_unlock();
0) 0.495 us | current_kernel_time();
1) | it_real_fn() {
0) 1.602 us | }
1) 0.728 us | __rcu_read_lock();
0) | sys_nanosleep() {
0) | hrtimer_nanosleep() {
0) 0.526 us | hrtimer_init();
1) 0.418 us | __rcu_read_lock();
0) | do_nanosleep() {
1) 1.114 us | _spin_lock_irqsave();
[...]
0) | __kmalloc() {
1) 2.760 us | }
0) 0.556 us | get_slab();
1) | mwait_idle() {
0) 1.851 us | }
0) | /* after nano */
0) | kfree() {
0) 0.486 us | __phys_addr();
trace_marker 파일에 쓴 데이터는 function graph tracer안에서 코멘트로 보인다.
Notice that the writes to trace_marker show up as comments in the function graph tracer.
첫 번째 열은 CPU ID를 보여준다. 위의 결과처럼 여러 CPU가 겹치면, 결과를 읽기가 어려울 수도 있다.
The first column here represents the CPU. When we have the CPU traces interleaved like this, it may become hard to read the trace.
이런 결과를 쉽게 필터링할 수 있는 툴이나 per_cpu 디렉토리를 사용할 수 있다. per_cpu 디렉토리는 debugfs의 tracing 디렉토리 안에 있다.
The tool grep can easily filter this, or the per_cpu trace files may be used. The per_cpu trace files are located in the debugfs tracing directory under per_cpu.
[tracing]# ls per_cpu
cpu0 cpu1 cpu2 cpu3 cpu4 cpu5 cpu6 cpu7
CPU 개수만큼 존재하는 디렉토리에는 해당 CPU를 위한 trace만 보여주는 trace 파일이 있다.
There exists a trace file in each one of these CPU directories that only show the trace for that CPU.
다른 CPU의 간섭없이 function graph tracer를 편히 보기 위해서는 per_cpu/cpu0/trace를 보면 된다.
To get a nice view of the function graph tracer without the interference of other CPUs just look at per_cpu/cpu0/trace.
[tracing]# cat per_cpu/cpu0/trace
0) | __kmalloc() {
0) 0.528 us | get_slab();
0) 2.271 us | }
0) | /* before nano */
0) | kfree() {
0) 0.475 us | __phys_addr();
0) 2.062 us | }
0) 0.608 us | inotify_inode_queue_event();
0) 0.485 us | __fsnotify_parent();
0) 0.488 us | inotify_dentry_parent_queue_event();
0) 1.106 us | fsnotify();
[...]
0) 0.721 us | _spin_unlock_irqrestore();
0) 3.380 us | }
0) | audit_syscall_entry() {
0) 0.495 us | current_kernel_time();
0) 1.602 us | }
0) | sys_nanosleep() {
0) | hrtimer_nanosleep() {
0) 0.526 us | hrtimer_init();
0) | do_nanosleep() {
0) | hrtimer_start_range_ns() {
0) | __hrtimer_start_range_ns() {
0) | lock_hrtimer_base() {
0) 0.866 us | _spin_lock_irqsave();
[...]
0) | __kmalloc() {
0) | get_slab() {
0) 1.851 us | }
0) | /* after nano */
0) | kfree() {
0) 0.486 us | __phys_addr();
커널안의 tracer를 비활성화하기
커널 드라이버의 개발중에는 테스트 중에 이상한 에러가 나타날 수 있다. 아마도 드라이버가 sleep state에 갇혀있고 깨어나지 않을 것이다.
During the development of a kernel driver there may exist strange errors that occur during testing. Perhaps the driver gets stuck in a sleep state and never wakes up.
커널 이벤트가 발생했을 때 유저 공간에서 tracer를 비활성화하는 것은 어렵고 유저가 trace를 멈추기 전에 보통 버퍼 오버 플로우를 유발해서 관련 정보가 날라가게 된다.
Trying to disable the tracer from user space when a kernel event occurs is difficult and usually results in a buffer overflow and loss of the relevant information before the user can stop the trace.
커널 안에서 잘 동작하는 두가지의 함수 tracing_on()과 tracing_off()가 있다. 두 함수는 단지 0과 1를 tracing_on파일에 echo하면 동작한다.
There are two functions that work well inside the kernel: tracing_on() and tracing_off(). These two act just like echoing “1″ or “0″ respectively into the tracing_on file.
만약 커널안에서 체크되어야 할 몇가지 조건이 있다면, tracer는 아래와 같은 코드를 추가해서 멈출 수 있다.
If there is some condition that can be checked for inside the kernel, then the tracer may be stopped by adding something like the following:
if (test_for_error())
tracing_off();
다음으로 몇개의 trace_printk()를 추가해서, 다시 컴파일하고 커널을 부팅한다.
Next, add several trace_printk()s (see part 1), recompile, and boot the kernel.
function tracer 이나 function graph tracer를 활성화할 수 있고 에러 상황이 발생하는 것을 단지 기다리면 된다.
You can then enable the function or function graph tracer and just wait for the error condition to happen.
tracing_on 파일을 검사하면 오류 조건이 발생한 시기를 알 수 있다. 커널이 tracing_off()를 호출하면 “1”에서 “0”으로 전환된다.
Examining the tracing_on file will let you know when the error condition occurred. It will switch from “1″ to “0″ when the kernel calls tracing_off().
trace를 검사하거나 아래처럼 파일로 저장하면 된다.
After examining the trace, or saving it off in another file with:
cat trace > ~/trace.sav
다른 에러(another hit)를 검사하기 위해 trace를 계속할 수 있다. 계속하려면 1을 tracing_on에 에코하면된다.
you can continue the trace to examine another hit. To do so, just echo “1″ into tracing_on, and the trace will continue.
만약 tracing_off()를 호출하는 조건이 발생할 경우에도 유용하다. 조건이 정상 작동에 의해 트리거 된 경우 tracing_on에 “1”을 다시 에코하여 추적을 다시 시작하면 다음 번에 조건이 발생했을 때 비정상으로 인해서도 잘 작동한다.
This is also useful if the condition that triggers the tracing_off() call can be triggered legitimately. If the condition was triggered by normal operation, just restart the trace by echoing a “1″ back into tracing_on and hopefully the next time the condition is hit will be because of the abnormality.
ftrace_dump_on_oops
커널 크래쉬가 발생하는 경우가 많을 것이고 메모리와 크래쉬 상태를 검사하는 것은 프로그램 디버깅 과학보다 CSI 과학에 가깝다.
There are times that the kernel will crash and examining the memory and state of the crash is more of a CSI science than a program debugging science.
크래쉬 유틸리티와 함께 kdump/kexec를 사용하는 것은 크래시가 발생한 지점에서 시스템의 상태를 검사하는데 가치가 있는 방법이다. 하지만 크래쉬를 유발한 이벤트보다 먼저 어떤 일이 일어났는지를 보여주진 않는다.
Using kdump/kexec with the crash utility is a valuable way to examine the state of the system at the point of the crash, but it does not let you see what has happened prior to the event that caused the crash.
Ftrace를 활성화하고 부팅 파라미터에서 ftrace_dump_on_oops를 활성화하거나, /proc/sys/kernel/ftrace_dump_on_oops에 1을 에코하면, oops 혹은 패닉이 발생했을때 ftrace는 trace buffer를 아스키 포맷에 맞게 출력할 것이다.
Having Ftrace configured and enabling ftrace_dump_on_oops in the kernel boot parameters, or by echoing a “1″ into /proc/sys/kernel/ftrace_dump_on_oops, will enable Ftrace to dump to the console the entire trace buffer in ASCII format on oops or panic. Having the console output to a serial log makes debugging crashes much easier. You can now trace back the events that led up to the crash.
기본적인 ftrace ring buffer는 cpu마다 몇 메가가 넘기 때문에 콘솔에 출력하는 것은 오랜시간이 걸릴수도 있다. 링 버퍼의 사이즈를 줄이기 위해, kb단위로 원하는 만큼의 링 버퍼 사이즈를 buffer_size_kb에 쓸 수 있다.
Dumping to the console may take a long time since the default Ftrace ring buffer is over a megabyte per CPU. To shrink the size of the ring buffer, write the number of kilobytes you want the ring buffer to be to buffer_size_kb.
이 값은 CPU마다 할당된 링 버퍼의 사이즈를 나타내고 링 버퍼 전체 사이즈는 아니다.
Note that the value is per CPU, not the total size of the ring buffer.
[tracing]# echo 50 > buffer_size_kb
위의 경우는 CPU의 링 버퍼의 크기를 50kb로 설정한다.
The above will shrink the Ftrace ring buffer down to 50 kilobytes per CPU.
sysrq-z를 이용해서 ftrace 버퍼를 콘솔에 덤프할 수 있다.
You can also trigger a dump of the Ftrace buffer to the console with sysrq-z.
커널 덤프의 위치를 별도로 지정하기 위해, 커널은 ftrace_dump()를 직접 호출할 수 있다. 유념하자, 이 경우 ftrace를 영구히 비활성화할 수 있고 활성화를 위해 재부팅이 필요할 수도 있다. ftrace_dump()가 버퍼를 읽기 때문이다.
To choose a particular location for the kernel dump, the kernel may call ftrace_dump() directly. Note, this may permanently disable Ftrace and a reboot may be necessary to enable it again. This is because ftrace_dump() reads the buffer.
버퍼는 모든 컨텍스트(인터럽트,NMI, 스케쥴링)에서 쓰여질 수 있다. 하지만 버퍼를 읽는것은 lock을 필요로 한다. ftrace_dump() 수행이 가능하기 위해서는 locking이 비활성화되고 버퍼가 출력된 후에 비어져야 한다.
The buffer is made to be written to in all contexts (interrupt, NMI, scheduling) but the reading of the buffer requires locking. To be able to perform ftrace_dump() the locking is disabled and the buffer may end up being corrupted after the output.
/*
* The following code will lock up the box, so we dump out the
* trace before we hit that location.
*/
ftrace_dump();
/* code that locks up */
스택 tracing하기
토론의 마지막 토픽은 커널 스택의 크기를 검사하는 기능과 각 함수가 사용하는 스택영역이 얼마나 큰지를 검사하는 기능이다.
The final topic to discuss is the ability to examine the size of the kernel stack and how much stack space each function is using.
stack tracer를 활성화하는 것은 스택의 가장 큰 사용처가 어디에 위치해 있는지 보여줄 것이다.
Enabling the stack tracer (CONFIG_STACK_TRACER) will show where the biggest use of the stack takes place.
stack tracer는 function tracer 인프라에 포함되어 있다. 이 tracer는 ftrace의 링 버퍼를 사용하지 않지만, 모든 함수 호출을 후킹하기 위해서 function trace를 사용한다.
The stack tracer is built from the function tracer infrastructure. It does not use the Ftrace ring buffer, but it does use the function tracer to hook into every function call.
function tracer 인프라를 사용하기 때문에, 비활성화할 때는 오버헤드가 생기지 않는다. stack tracer를 활성화하기 위해, 1을 /proc/sys/kernel/stack_tracer_enabled에 에코하면 된다.
Because it uses the function tracer infrastructure, it does not add overhead when not enabled. To enable the stack tracer, echo 1 into /proc/sys/kernel/stack_tracer_enabled.
부팅도중에 최대 스택 크기를 보기 위해서는 커널 부팅 파라미터에 stacktrace를 추가하면 된다.
To see the max stack size during boot up, add “stacktrace” to the kernel boot parameters.
stack tracer는 스택의 크기를 매 함수 호출 때마다 체크한다. 만약 가장 마지막에 쓰여진 최대 크기보다 크다면, stack trace를 기록하고 새로운 크기로 최대 크기를 갱신한다.
The stack tracer checks the size of the stack at every function call. If it is greater than the last recorded maximum, it records the stack trace and updates the maximum with the new size.
현재 최대 크기를 보기위해서는 stack_max_size 파일을 보면 된다.
To see the current maximum, look at the stack_max_size file.
[tracing]# echo 1 > /proc/sys/kernel/stack_tracer_enabled
[tracing]# cat stack_max_size
2928
[tracing]# cat stack_trace
Depth Size Location (34 entries)
----- ---- --------
0) 2952 16 mempool_alloc_slab+0x15/0x17
1) 2936 144 mempool_alloc+0x52/0x104
2) 2792 16 scsi_sg_alloc+0x4a/0x4c [scsi_mod]
3) 2776 112 __sg_alloc_table+0x62/0x103
[...]
13) 2072 48 __elv_add_request+0x98/0x9f
14) 2024 112 __make_request+0x43e/0x4bb
15) 1912 224 generic_make_request+0x424/0x471
16) 1688 80 submit_bio+0x108/0x115
17) 1608 48 submit_bh+0xfc/0x11e
18) 1560 112 __block_write_full_page+0x1ee/0x2e8
19) 1448 80 block_write_full_page_endio+0xff/0x10e
20) 1368 16 block_write_full_page+0x15/0x17
21) 1352 16 blkdev_writepage+0x18/0x1a
22) 1336 32 __writepage+0x1a/0x40
23) 1304 304 write_cache_pages+0x241/0x3c1
24) 1000 16 generic_writepages+0x27/0x29
[...]
30) 424 64 bdi_writeback_task+0x3f/0xb0
31) 360 48 bdi_start_fn+0x76/0xd7
32) 312 128 kthread+0x7f/0x87
33) 184 184 child_rip+0xa/0x20
스택의 최대 사이즈를 보여줄 뿐만 아니라, 스택 사이즈를 각 함수가 얼마큼 쓰고 있는지도 보여준다.
Not only does this give you the size of the maximum stack found, it also shows the breakdown of the stack sizes used by each function.
write_cache_pages()가 304바이트를 스택에서 사용하고 있어 가장 많이 사용하는 함수가 된다. 그 뒤로는 224바이트를 사용하는 generic_make_request()이 있다.
Notice that write_cache_pages had the biggest stack with 304 bytes being used, followed by generic_make_request with 224 bytes of stack.
최대 크기를 리셋하기 위해, 0을 stack_max_size 파일에 echo하면 된다.
To reset the maximum, echo “0″ into the stack_max_size file.
[tracing]# echo 0 > stack_max_size
잠시 시스템을 유지하면 커널의 어느곳이 스택을 많이 쓰는지 알 수 있다. 하지만 stack tracer는 비활성화되어 있을때에는 오버헤드가 없다는것을 기억해야 한다.
Keeping this running for a while will show where the kernel is using a bit too much stack. But remember that the stack tracer only has no overhead when it is not enabled.
stack tracer가 동작중에는 약간의 성능 저하가 있다는 것을 알아챌 것이다.
When it is running you may notice a bit of a performance degradation.
stack tracer는 커널이 별도의 스택을 사용할때는 max stack size를 trace하지 않을것이다. 왜냐하면 interrupt는 자신의 스택을 가지고 있을것이고, 해당 스택에서는 stack trace가 동작하지 않을것이기 때문이다.
Note that the stack tracer will not trace the max stack size when the kernel is using a separate stack. Because interrupts have their own stack, it will not trace the stack usage there.
현재는 스택이 현재 태스크의 스택이 아닌 다른 스택일때, 스택의 맨위에 무엇이 있는지를 빠르게 볼 수 있는 쉬운 방법이 없기 때문이다. split stack을 사용할때, 프로세스는 아마 2개의 페이지를 스택으로 사용할 것이지만, 인터럽트 스택은 오직 하나의 페이지가 될것이다.
The reason is that currently there is no easy way to quickly see what the top of the stack is when the stack is something other than the current task’s stack. When using split stacks, a process stack may be two pages but the interrupt stack may only be one.
추후에 이런 문제는 수정되어야 하고, stack stracer를 사용할때 이 점을 유의해야 한다.
This may be fixed in the future, but keep this in mind when using the stack tracer.
결론(Conclusion)
ftrace는 매우 강력하고 설정하기 쉬운 툴이다. 다른 추가적인 툴은 필요없다. 이번 튜토리얼에서 보여준 모든것은 busybox만 설치되어 있다면 임베디드 장치에서 사용될 수 있다. ftrace 인프라를 이용하는 것은 찾기어려운 경쟁 상황을 디버깅하는데 필요한 시간을 줄여준다.
Ftrace is a very powerful tool and easy to configure. No extra tools are necessary. Everything that was shown it this tutorial can be used on embedded devices that only have Busybox installed. Taking advantage of the Ftrace infrastructure should cut the time needed to debug that hard-to-find race condition.
나는 function tracer와 function graph tracer를 trace_printk()와 tracing_off()를 함께 쓰면서 커널을 디버깅할때 사용하는 주요툴이 되면서 더이상 printk()를 사용하지 않는다.
I seldom use printk() any more because using the function and function graph tracers along with trace_printk() and tracing_off() have become my main tools for debugging the Linux kernel.
'커널 번역(기사,문서)' 카테고리의 다른 글
[번역] admin-guide/tainted-kernel.rst (0) | 2018.09.08 |
---|---|
[번역] lwn – Debugging the kernel using Ftrace — part 1 (0) | 2018.09.08 |
[번역] scheduler/completion.txt (0) | 2018.09.08 |
[번역] scheduler/sched-arch.txt (0) | 2018.09.08 |
[번역] dev-tools/kmemleak.txt (0) | 2018.09.08 |