printk
사용법
동작이나 함수 멤버등을 확인해보고 싶은 함수내에 printk() 함수 사용
커널로그는 /var/log/kern.org 파일에서 확인 가능하다.
printk("[+][debug] message [F: %s, L:%d]: caller:(%pS)\n",
__func__, __LINE__, (void *)_builtin_return_address(0));
사용 이유
printk 함수는 다양한 로그 레벨과 형식을 지원하여 디버깅 및 로깅 목적으로 사용된다.
함수의 심볼정보를 출력하기 위해 사용하는데
함수 주소를 넘겨 %pS로 심볼정보를 출력한다던지, %p를 통해 주소를 출력하는 용도로 사용한다.
심볼정보란?
쉽게 말하면 함수의 메타데이터이고,
함수명,리턴타입, 매개변수 타입 및 개수를 말한다.
[+] process: kworker/2:3
[+][debug] message [F:insert_wq_barrier, L:2354] caller(workqueue_cpu_down_callback+0x90/0xac)
/var/log/kern.org 에서 위와 같은 로그를 볼 수 있을것이다.(insert_wq_barrier함수가 호출 된다면. 즉, 워크큐를 사용할 정도의 로드(부하)를 시스템에 준다면)
여기서 printk를 실행한 함수는 kworker /2:3이라는 프로세스이고, printk를 호출한 함수는 insert_wq_barrier이다.
또한 insert_wq_barrier함수는 workqueue_cpu_down_callback함수가 호출했다.
주의할 점
만약 printk를 사용한 함수가 매우 자주 호출되는 함수라면 printk를 자주 출력해서 시스템이 락업 걸릴 위험이 있다.
printk는 파일시스템의 도움으로 로그를 콘솔버퍼에 저장하는 세부 동작을 수행하고, 이 동작들을 콘솔 드라이버에서 처리하며, 커널 로그를 저장하는 동작을 백그라운드로 처리한다.
dump_stack
사용법
헤더파일인 #include를 추가하고
콜 스택을 확인하고 싶은 함수에서 dump_stack(); 을 사용한다.
콜스택이란?
프로그램은 main 함수에서 시작하여 다른 함수들을 호출하며 작동한다.
이때 만약 main 함수에서 a 함수를 호출하고 a 함수에서 b 함수를 호출하게 된다면
l b l
l a l
l main l
메모리 함수 스택에 다음과 같은 형태로 저장되어 있을 것이다.
이를 콜 스택 이라고 부르는 것 같다. (정확하지 않을 수 있음)
dump_stack을 추가한 후 빌드, 설치 과정을 거친다.
커널 로그를 확인해 보자.
첫번째 줄은 콜스택을 실행한 프로세스 정보
CPU3을 이용중인 PID 498을 갖는 프로세스라는 의미를 포함한다.
해석하는 방법은 맨 아래줄의 ret_fast_syscall함수가 sys_clone함수를 호출하고 sys_clone이 _do_fork를 호출하는 방식으로 스택과 같은 형태로 해석하면 된다.
주의할 점
dump_stack함수 또한 내부적으로 하는 동작이 많기때문에 자주 호출되는 함수에는 사용하면 락업에 걸릴 확률이 printk보다 높다. 해당 함수는 stack pointer 와 frame pointer를 이용해 함수 호출 동작을 추적한다.
참고
함수 원형에서 asmlinkage 사용하는 이유?
보통 함수를 부르고 인자를 넘길때 레지스터를 통해 하는데 arm mips는 레지스터가 남아서 괜찮지만
x86은 그렇지 않아서 이 인자를 넘기는 것을 스택을 통해 하기 위함.
LTO(컴파일러)기능 -> 콜러와 콜리관계에서 링커가 callee가 한번만 사용된다고 판단하면 inline화 한다.
함수나 객체가 inline화 되지않게 막아주는 역할 즉 컴파일러가 무리하게 inline화 하는걸 막는다.
ftrace (function trace)
ftrace 특징
인터럽트, 스케줄링 등의 이벤트를 추적할 수 있다.
트레이싱할 함수를 지정하면 코드를 수정하고 커널을 빌드, 설치할 필요가 없다.
함수를 어느 프로세스가 실행하는지 알 수 있다.
함수 실행 시각을 알 수 있다.
다른 디버깅 함수(dump, printk)와 달리 시스템에 큰 영향을 주지 않는다.
사용법
ftrace 설정 파일입니다. ftrace는 커널에 내장되어 있다.
위 파일들에 0 또는 1 또는 특정 텍스트(함수이름, 트레이서이름 등)을 입력해 트레이싱 준비를 한다.
이는 편하게 shell script로 만들어서 사용한다.
문단 단위로 설정을 분석 해보자.
먼저 트레이싱을 비활성화 합니다.
1초의 sleep은 쉘스크립트, 즉 비활성화 동작을 기다려 주는 것이다.
/sys/kernel/debug/tracing/tracing_on 이름만 봐도 어떤 파일인지 짐작이 간다.
(0 -> 비활성화, 1 -> 활성화)
/sys/kernel/debug/tracing/events/enable 를 비활성화한다.
이벤트는 아래에서 설명함
/sys/kernel/debug/tracing/events/set_ftrace_filter
더미 함수에대한 필터 활성화한다.
이 파일은 사용자가 어떤 함수를 트레이싱 할 지 함수 목록을 설정하는 파일임.
set_ftrace_filter는 설정하지 않았을 때 모든 함수가 저장되어 있다.
따라서 커널이 실행될때 한 번만 수행되는 secondary_start_kernel을 더미로 입력해야한다.
echo function > /sys/kernel/debug/tracing/current_tracer
트레이서의 종류 즉 트레이싱 결과를 어떤 형식으로 보여줄 것인지 설정.
echo function에서 function 외에 function_graph,nop 과 같은 옵션이 있다.
예시로 function_graph 트레이서 로그를 보자.
0) -> 0번 CPU사용 중
+ -> 10us이상일때 (100us이상일땐 !)
43.556us -> sdio_writel(); 함수가 실행되는데 걸린 시간
50.222us -> brcmf_sdiod_writel [brcmfmac](); 함수가 실행되는데 걸린 시간
irq/36--79 => kworker-17102
-> 하이픈 왼쪽은 프로세스 이름, 하이픈 오른쪽의 숫자는 프로세스 번호
-> 0번CPU에서 irq/36--79프로세스를 실행시키다 kworker-17102프로세스로 스케줄링 하는 과정 같음..(정확x)
brcmf_sdiod_writel [brcmfmac]() 함수가 sdio_writel() 함수를 호출한 형태를 볼 수 있다.
echo vfs_open > /sys/kernel/debug/tracing/events/set_ftrace_filter
심플하게 가장 중요한 부분이다.
트레이싱 하고싶은 함수를 설정하는 부분이다.
/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable
/sys/kernel/debug/tracing/events/irq/irq_handler_entry/enable
sched
설정시 프로세스 스케줄링 동작과 스케줄링 프로파일링을 트레이싱 하는 이벤트를 볼 수 있다.
sched_wakeup : 프로세스 깨우는 동작
sched_switch : 컨텍스트 스위칭 동작
irq
설정시 인터럽트와 소프트웨어 인터럽트를 트레이싱 하는 이벤트를 볼 수 있다.
irq_handler_entry : 인터럽트가 발생한 시각과 인터럽트 번호 및 이름 출력
irq_handler_exit : 인터럽트 핸들링 완료
softirq_raise : Soft IRQ 서비스 실행 요청
softirq_entry : Soft IRQ 서비스 실행 시작
softirq_exit : Soft IRQ 서비스 실행 완료
/sys/kernel/debug/tracing/options/func_stack_trace
set_ftrace_filter를 통해 트레이싱하기로한 함수의 콜 스택을 출력하는 설정
/sys/kernel/debug/tracing/options/sym-offset
함수의 논리 주소와 물리 주소간의 오프셋을 알아내어
하드웨어(메모리?)에서 이름,인자,변수 등을 식별하여 더 정확한 정보 제공
/sys/kernel/debug/tracing/tracing_on
마지막으로 tracing을 활성화 시켜 동작하게 한다.
트레이서를 동작시키고,
이제 원하는 함수를 실행시켜 로그를 남긴후에
위 쉘스크립트 코드를 만들어
트레이싱 종료, 로그를 현재 디렉터리로 가져온다.
cat이나 vi로 ftrace_log.c 파일을 확인
참고 자료
https://www.kernel.org/doc/Documentation/trace/ftrace.rst
ctags
ctags란?
리눅스 환경에서 코드를 이해하기 위해 함수,변수,매크로 등 프로그래밍 언어적 요소를 인덱싱하여
'tags' 파일을 생성하며, 원하는 함수나 변수를 찾아 그 요소의 파일로 이동 및 원래 파일로 복귀를 도와주는 툴이다.
(apt-get과 같은 패키지 관리자를 이용해 설치해야함)
쉽게 말하면 작성한 코드들의 요소(변수,함수 등)을 따로 정리해두는 'tags' 파일을 생성하고,
요소(코드)의 위치로 이동 및 복귀를 돕는 툴이다.
사용법
ctags -R *
기본적으로 위와 같은 형태로 사용하며 -R옵션은 recursive라는 의미이고,
이는 현재 위치에 있는 모든 파일과 디렉토리의 자식,손자..의 파일을 인덱싱하여 'tags'라는 파일을 만들라는 명령어 이다.
위 명령어를 사용하면 현재디렉토리에 tags라는 파일이 생성된다.
임의로 malloc이라는 함수를 찾아보자.
tags를 생성한 디렉토리에서 vi로 아무 파일을 열어보고, esc를 눌러 명령어 입력 모드로 전환한다.
Ctrl+] 함수가 정의된 파일로 이동
Ctrl+t 이동하기 전 단계의 위치로 이동
:ta ~~ 키워드와 일치하는 태그위치
:ts <function-name> 같은 이름의 function-name이 여러개 일때, 목록을 보여준다. 번호를 이용해서 선택할 수 있다
:tn ~~ 여러개의 함수이름이 존재할 때, 다음 함수를 선택한다.
:tp ~~ 이전 함수를 선택한다.
:tfirst ~~ 가장 처음에 찾았던 함수를 선택한다.
:tlast ~~ 가장 마지막 함수를 선택한다.
:tags 이동했던 태그목록들 출력
:ts malloc
위 명령어를 입력한다.
위와같은 화면이 나오게 되는데 여기서
# : 사용자가 선택하기 위한 임의의 리스트 인덱스
pri : F(Fully matched),C( in Current file), S(Static) 등의 의미 (아래 참조)
kind : f(function), v(variable), d(macro definition), t(typedef), s(structure), m or g(member of enum, struct, union) 등이있다.
보라색 글씨 : Tag이름 ex) malloc
파란색 글씨 : 요소가 위치한 파일경로 ex) lib/inflate.c
보라색 아래의 흰 글씨 : 요소가 작성된 line번호 or 요소의 표현식 (코드 부분)
7번 요소의 위치로 이동해 보자.
해당 화면이 나오면 코드를 읽을 수 있게 되고 Ctrl + t입력하여 이동하기 전으로 돌아갈 수 있다.
cscope
cscope란?
ctags와 비슷하지만 조금 더 많은 내용을 추적할 수 있다.
예를 들어
어떤 함수를 호출한 함수
어떤 함수가 호출한 함수
찾고 싶은 문자열
등 다양하게 확인해 볼 수 있다.
사용법
cscope -Rbq
-R : recursive(하위 디렉터리 까지 보겠다는 뜻)
-b : 데이터베이스 생성
-q : 검색 프롬프트 사용지정
검색하는 방법 -1
cscope -d
명령어 사용 하여 데이터베이스를 open
데이터 베이스에서 방향키 또는 enter(return)키로 검색 유형을 선택할 수 있으며 종료는 Ctrl + d 이다.
검색 유형에는 문자열 찾기, 함수 찾기, 심볼찾기, 호출한 함수 찾기 등등 이다.
단순히 문자열 찾는 것만으로도 ctags보다 넓고, 호출함수도 찾아주기에 더 깊다고 볼 수 있다.
? + enter를 통해 cscope 데이터 베이스 활용법에 대해 알 수 있다.
검색하는 방법 -2
vi 에서도 검색이 가능하다.
do_skip 함수가 call하는 함수를 찾아보는 예시로 포스팅을 마치겠다.
:cs find <options> keyword
위는 기본적인 명령어 형태이고, 아래 옵션을 통해 검색 유형을 선택할 수 있다.
0 (s) - 키워드를 검색
1 (g) - 선언 (정의) 되어 있는 부분으로 이동
2 (d) - 이 함수가 호출 하는 함수 목록 출력
3 (c) - 이 함수를 호출하는 함수 출력
4 (t) - 문자열 검색
5 (e) - 확장 정규식을 사용하여 검색
7 (f) - 파일 검색 (파일 이름 검색)
8 (i) - 이 파일을 include 하는 파일을 검색
함수를 호출하는 라인, 함수 호출 코드, 함수위치 등이 포함되어 있다.
'linux' 카테고리의 다른 글
OS(operating system) 개발하고자 하면서... (0) | 2023.03.21 |
---|