사실, 모듈/드라이버를 요구하는 프로세스를 나열하는 방법이있는 것처럼 보이지만 (리눅스 커널 문서 외부에서) 광고하지 못했기 때문에 여기에 메모를 적어 두겠습니다 :
우선, @haggai_e 님의 답변에 대해 감사드립니다. 사용 카운트 (refcount)를 관리하는 책임자 인 함수 try_module_get
및 try_module_put
에 대한 포인터가 프로 시저를 추적 할 수있게 해주는 키입니다.
이 온라인에 대한 추가 정보를 보려면 어떻게 든 비틀 거 렸습니다 Linux-Kernel Archive: [PATCH 1/2] tracing: Reduce overhead of module tracepoints; 마침내 커널에있는 시설을 가리키며 "추측하기"라고합니다. 이에 대한 문서는 Documentation/trace - Linux kernel source tree 디렉토리에 있습니다. 특히, 두 파일은 추적 기능을 설명합니다 (events.txt 및 ftrace.txt).
그러나 실행중인 Linux 시스템에는 짧은 "추적 미니 하우투"가 /sys/kernel/debug/tracing/README
(I'm really really tired of people saying that there's no documentation…도 표시)입니다. 커널 소스 트리에서이 파일은 실제로 파일 kernel/trace/trace.c에 의해 생성됩니다. 우분투 natty
에서이를 테스트 및 /sys
는 루트가 소유하고 있기 때문에 그 거의 모든 간다 sudo cat
에서 또는
sudo less /sys/kernel/debug/tracing/README
... 그리고, 당신은이 파일을 읽을 sudo
를 사용할 필요가 있습니다했습니다 여기서 설명 할 /sys
하에 다른 동작을 수행한다. 우선
, 여기에 단순히 문자열 "이 testmod입니다 반환하는 /proc/testmod-sample
파일 노드를 생성한다 (필자는 언급 된 자원에서 조립) 간단한 최소한의 모듈/드라이버 코드입니다.이 읽을 때 ";이 testmod.c
입니다 :
/*
https://github.com/spotify/linux/blob/master/samples/tracepoints/tracepoint-sample.c
https://www.linux.com/learn/linux-training/37985-the-kernel-newbie-corner-kernel-debugging-using-proc-qsequenceq-files-part-1
*/
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h> // for sequence files
struct proc_dir_entry *pentry_sample;
char *defaultOutput = "This is testmod.";
static int my_show(struct seq_file *m, void *v)
{
seq_printf(m, "%s\n", defaultOutput);
return 0;
}
static int my_open(struct inode *inode, struct file *file)
{
return single_open(file, my_show, NULL);
}
static const struct file_operations mark_ops = {
.owner = THIS_MODULE,
.open = my_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int __init sample_init(void)
{
printk(KERN_ALERT "sample init\n");
pentry_sample = proc_create(
"testmod-sample", 0444, NULL, &mark_ops);
if (!pentry_sample)
return -EPERM;
return 0;
}
static void __exit sample_exit(void)
{
printk(KERN_ALERT "sample exit\n");
remove_proc_entry("testmod-sample", NULL);
}
module_init(sample_init);
module_exit(sample_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mathieu Desnoyers et al.");
MODULE_DESCRIPTION("based on Tracepoint sample");
이 모듈로 구축 할 수
다음 Makefile
(그냥 testmod.c
과 같은 디렉토리에 있고, 그 같은에 make
을 실행 디렉토리).이 모듈/드라이버가 내장되면
CONFIG_MODULE_FORCE_UNLOAD=y
# for oprofile
DEBUG_INFO=y
EXTRA_CFLAGS=-g -O0
obj-m += testmod.o
# mind the tab characters needed at start here:
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
, 출력이 커널 오브젝트 파일입니다 testmod.ko
,
이 시점에서 try_module_get
및 try_module_put
과 관련된 이벤트 추적을 준비 할 수 있습니다. 사람들은 /sys/kernel/debug/tracing/events/module
에 내 시스템에서 추적이 기본적으로 것을
가
$ sudo ls /sys/kernel/debug/tracing/events/module
enable filter module_free module_get module_load module_put module_request
참고 활성화 :
이
$ sudo cat /sys/kernel/debug/tracing/tracing_enabled
1
... 그러나, 모듈 (특히) 추적하는 것은 아니다 :
$ sudo cat /sys/kernel/debug/tracing/events/module/enable
0
이제 필터를 작성해야 module_get
, module_put
등 이벤트에 반응하지만 testmod
모듈에만 반응해야합니다. 여기
$ sudo cat /sys/kernel/debug/tracing/events/module/module_put/format
name: module_put
ID: 312
format:
...
field:__data_loc char[] name; offset:20; size:4; signed:1;
print fmt: "%s call_site=%pf refcnt=%d", __get_str(name), (void *)REC->ip, REC->refcnt
우리는 우리가에 대해 필터링 할 수 있습니다 드라이버 이름을 보유하고 name
라는 필드가 발생한 것을 볼 수 있습니다이를 위해 우리는 먼저 이벤트의 형식을 확인해야합니다. 필터를 만들려면, 우리는 단순히 echo
해당 파일에 필터 문자열 : 여기
sudo bash -c "echo name == testmod > /sys/kernel/debug/tracing/events/module/filter"
, 우리가 sudo
전화를해야하기 때문에, 우리는 sudo
의 인수 명령으로 전체 echo
재 포장해야한다는 첫째 주 -ed bash
. 둘째, 특정 이벤트 (module/module_put/filter
등)가 아닌 "부모"module/filter
에게 편지를 썼기 때문에이 필터는 module
디렉토리의 "children"으로 나열된 모든 이벤트에 적용됩니다.
마지막으로, 우리는 모듈에 대한 추적을 활성화 : 우리는 추적 로그 파일을 읽을 수있는이 시점에서
sudo bash -c "echo 1 > /sys/kernel/debug/tracing/events/module/enable"
; 나를 위해, 차단 읽기, "파이프"추적 파일의 버전 일 - 다음과 같이 :
sudo cat /sys/kernel/debug/tracing/trace_pipe | tee tracelog.txt
이 시점에서, 우리는 로그에 아무것도 표시되지 않습니다 - 그래서로드 할 때 (그리고 활용 trace_pipe
이 읽고있는 경우 등)에서 다른 터미널에서) 드라이버를 (제거 :
# tracer: nop
#
# TASK-PID CPU# TIMESTAMP FUNCTION
# | | | | |
insmod-21137 [001] 28038.101509: module_load: testmod
insmod-21137 [001] 28038.103904: module_put: testmod call_site=sys_init_module refcnt=2
rmmod-21354 [000] 28080.244448: module_free: testmod
:
$ sudo insmod ./testmod.ko
$ cat /proc/testmod-sample
This is testmod.
$ sudo rmmod testmod
을 우리가 trace_pipe
이 읽고있는 터미널로 갈 경우, 우리는 같은 것을 볼 수3210
드라이버가로드 될 때 (insmod
) 또는 언로드 된 경우 (rmmod
)에만 ref3ount가 변경됩니다. cat
을 통해 읽을 때가 아닙니다. 따라서 우리는 단순히 trace_pipe
에서 CTRL + C으로 읽기를 중단 할 수 있습니다. 그리고 모두 추적 중지 :
여기
sudo bash -c "echo 0 > /sys/kernel/debug/tracing/tracing_enabled"
는 대부분의 예를 참조 참고로 여기에 파일 /sys/kernel/debug/tracing/trace
을 읽는 대신 trace_pipe
에. 그러나 한 가지 문제는이 파일이 "파이프 처리"되지 않기 때문입니다 (이 trace
파일에 tail -f
을 실행해서는 안 됨). 대신 각 작업 후에 trace
을 다시 읽어야합니다. 첫 번째 insmod
이후에 우리는 cat
에서 동일한 출력을 얻습니다. trace
및 trace_pipe
; 그러나, rmmod
후 trace
파일을 읽는 것은 줄 것이다 :
<...>-21137 [001] 28038.101509: module_load: testmod
<...>-21137 [001] 28038.103904: module_put: testmod call_site=sys_init_module refcnt=2
rmmod-21354 [000] 28080.244448: module_free: testmod
을 ... 그이있다 :이 시점에서, insmod
이미 오래 종료되었다, 그래서 그 과정에서 더 이상 존재하지 않습니다 목록에 있으므로 기록 된 프로세스 ID (PID)를 통해 찾을 수 없습니다. 따라서 프로세스 이름으로 빈 <...>
이 표시됩니다. 따라서이 경우에는 trace_pipe
의 실행 출력을 (tee
을 통해) 기록하는 것이 좋습니다. 또한,/리셋을 취소하기 위해 점에 유의 /를 trace
파일을 삭제, 하나는 단순히에 0을 기록 :이 반 직관적 보인다면
sudo bash -c "echo 0 > /sys/kernel/debug/tracing/trace"
는 trace
는 특수 파일이므로주의하고, 항상 파일을보고합니다 어쨌든 0의 크기 :
$ sudo ls -la /sys/kernel/debug/tracing/trace
-rw-r--r-- 1 root root 0 2013-03-19 06:39 /sys/kernel/debug/tracing/trace
... "완전"인 경우에도 마찬가지입니다. 그와 같은 grep
등 모든 호출 (도 배경) 로그 것 -
마지막으로, 우리는 필터를 구현하지 않은 경우, 우리는 모든 모듈이 실행중인 시스템에서 호출 의 로그를 얻은 것이 있습니다 binfmt_misc
모듈을 사용하십시오.
...
tr-6232 [001] 25149.815373: module_put: binfmt_misc call_site=search_binary_handler refcnt=133194
..
grep-6231 [001] 25149.816923: module_put: binfmt_misc call_site=search_binary_handler refcnt=133196
..
cut-6233 [000] 25149.817842: module_put: binfmt_misc call_site=search_binary_handler refcnt=129669
..
sudo-6234 [001] 25150.289519: module_put: binfmt_misc call_site=search_binary_handler refcnt=133198
..
tail-6235 [000] 25150.316002: module_put: binfmt_misc call_site=search_binary_handler refcnt=129671
...이것은 약간의 오버 헤드를 추가합니다 (로그 데이터 양과 생성에 필요한 처리 시간 모두에서). 하지만 쉬운 명령 줄 인터페이스를 통해 -이를 보면서
, 나는 거의 상기와 유사한 작업을 수행하는 도구 trace-cmd를 의미하는 Debugging Linux Kernel by Ftrace PDF 우연히. trace-cmd
에 대한 "프런트 - 엔드 리더"GUI는 KernelShark입니다. 이 두 가지는 Debian/Ubuntu 저장소에 sudo apt-get install trace-cmd kernelshark
을 통해 있습니다. 이러한 도구는 위에서 설명한 절차의 대안 일 수 있습니다. 마지막으로, 위의 testmod
예제가 여러 클레임의 컨텍스트에서 실제로 사용되지는 않지만 필자는 동일한 추적 절차를 사용하여 코딩중인 USB 모듈이 반복적으로 USB 장치가 연결되자 마자 바로 pulseaudio
을 요청하므로 절차가 이러한 사용 사례에서 효과가있는 것처럼 보입니다.
"무엇을"어떤면에서? 어떤 코드? 어떤 모듈? 어떤 사용자입니까? 무슨 프로그램 요? 이 약간 프로그래밍에 관련된 느낌이 들지 않습니다. 재미있는 아무 것도 없습니다. –
글쎄, _is_ 프로그래밍 관련, 내가 커널 모듈을 쓰고 있기 때문에 묻고 있습니다. – mipadi
해결하려는 프로그래밍 문제를 보여주는 질문을 명확히하십시오. –