2009-01-15 3 views
61

커널 모듈을로드하고로드 된 모듈을 lsmod과 함께 나열하면 모듈의 "사용 횟수"(모듈에 대한 참조가있는 다른 모듈의 수)를 얻을 수 있습니다. 그래도 을 알아낼 방법이 있습니까?은 모듈을 사용하고 있습니까?리눅스 커널 모듈을 사용하고있는 것이 무엇인지 알아낼 방법이 있습니까?

문제점은 내가 개발중인 모듈이 사용 횟수가 1이고 따라서 rmmod을 사용하여 언로드 할 수 없다는 것이지만 "by"열은 비어 있습니다. 이것은 모듈을 다시 컴파일하고 다시로드 할 때마다 컴퓨터를 재부팅해야한다는 것을 의미합니다 (또는 최소한 언로드 할 다른 방법을 찾지 못했습니다).

+0

"무엇을"어떤면에서? 어떤 코드? 어떤 모듈? 어떤 사용자입니까? 무슨 프로그램 요? 이 약간 프로그래밍에 관련된 느낌이 들지 않습니다. 재미있는 아무 것도 없습니다. –

+1

글쎄, _is_ 프로그래밍 관련, 내가 커널 모듈을 쓰고 있기 때문에 묻고 있습니다. – mipadi

+0

해결하려는 프로그래밍 문제를 보여주는 질문을 명확히하십시오. –

답변

1

lsof 또는 fuser 일 수 있습니다.

+2

실제로 이것을 시도 했습니까? –

+0

처음에 생각했지만 동작하지 않습니다. – mipadi

+0

'lsof'는 그것을 이해하는 데 도움이되었습니다. +1 –

4

모든 모듈은 다른 모듈 (lsmod의 Used by 열)에 의존하는 목록입니다. 모듈이로드 된 이유, 모듈이 아직로드되어 있지 않은 경우 또는 모듈을 언로드하면 손상 될 수있는 모듈과 모듈에 의존하는 모든 것을 알려주는 프로그램을 작성할 수 없습니다.

6

Linux Kernel Module Programming Guide에서 모듈의 사용 횟수는 try_module_gettry_module_put 함수로 제어됩니다. 아마도 이러한 함수가 모듈에 대해 호출되는 위치를 찾을 수 있습니다.

40

사실, 모듈/드라이버를 요구하는 프로세스를 나열하는 방법이있는 것처럼 보이지만 (리눅스 커널 문서 외부에서) 광고하지 못했기 때문에 여기에 메모를 적어 두겠습니다 :

우선, @haggai_e 님의 답변에 대해 감사드립니다. 사용 카운트 (refcount)를 관리하는 책임자 인 함수 try_module_gettry_module_put에 대한 포인터가 프로 시저를 추적 할 수있게 해주는 키입니다.

이 온라인에 대한 추가 정보를 보려면 어떻게 든 비틀 거 렸습니다 Linux-Kernel Archive: [PATCH 1/2] tracing: Reduce overhead of module tracepoints; 마침내 커널에있는 시설을 가리키며 "추측하기"라고합니다. 이에 대한 문서는 Documentation/trace - Linux kernel source tree 디렉토리에 있습니다. 특히, 두 파일은 추적 기능을 설명합니다 (events.txtftrace.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_gettry_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에서 동일한 출력을 얻습니다. tracetrace_pipe; 그러나, rmmodtrace 파일을 읽는 것은 줄 것이다 :

<...>-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을 요청하므로 절차가 이러한 사용 사례에서 효과가있는 것처럼 보입니다.

+5

의견을 주셔서 감사합니다. @RichardHansen - 질문은 "모듈을 사용중인 이유를 파악하는 방법이 있습니까?"입니다. 모듈 추적에서'rmmod-21354' 또는'tr-6232' (프로세스 이름 - 프로세스 ID)가 module_put을 수행하는 것, 즉 모듈의 refcount를 변경한다는 것을 볼 수 있습니다. 그러한 프로세스는 모듈을 "사용"하고 있습니다. 그래서 나는 그것이 OP가 요구 한 것을 정확하게 대답한다고 주장 할 것입니다 ... 건배! – sdaau

2

rmmod를 --force 옵션없이 사용하면 모듈을 사용하는 내용을 알려줍니다. 예 : 그들은 모듈을 다시로드 할 수없는 이유를 알아 내기 위해 필사적 인 사람들을위한

$ lsmod | grep firewire 
firewire_ohci   24695 0 
firewire_core   50151 1 firewire_ohci 
crc_itu_t    1717 1 firewire_core 

$ sudo modprobe -r firewire-core 
FATAL: Module firewire_core is in use. 

$ sudo rmmod firewire_core 
ERROR: Module firewire_core is in use by firewire_ohci 

$ sudo modprobe -r firewire-ohci 
$ sudo modprobe -r firewire-core 
$ lsmod | grep firewire 
$ 
+3

글쎄, 그건 일반적으로 정확하지 않습니다 : 내 컴퓨터에있다 : '$ lsmod | grep snd snd_seq 47263 1 snd_timer 19130 1 snd_seq snd_seq_device 5100 1 snd_seq ... ' ; 그래서'snd_seq'는 무언가 (refcount가 1)에 의해 요구되었지만, 그 이유가 무엇인지 알 수 없습니다. 왜냐하면 그것이 비어 있고 다른 모듈이 특별히 주장하지 않는 이유입니다. (하지만 아마도 하나의'ftrace'가 이미 커널을 시작할 때부터 부트 프로세스 중 하나를 발견 할 수 있습니다.) – sdaau

+0

모든 경우에 작동하지 않는 것 같습니다. – Martin

+3

이것은 lsmod가 "used by"열에 무언가를 표시하는 경우에만 작동합니다. rmmod는 lsmod가 의존성 표시와 관련하여 더 이상 논리를 갖지 않습니다. – dannysauer

-2

, 나는 "에는 modinfo"를 사용하여 현재 사용되는 모듈의 경로를 얻기

  • 하여이 문제를 해결 할 수 있었다 나는 그것이
  • 를 입력하면 "modprobe를 DRIVER_NAME.ko"에 있던 경로에로드하고 싶은 새 모듈을 복사 그것을
  • 을 -rfing
  • RM. 모듈에
+0

이 답변은 실제로 묻는 질문에 대답하지 않습니다. – kelnos

0

시도의 KGDB 및 설정 중단 점