모듈 insmod와 rmmod 오류 해결 방안

5824 단어 linux 커널 모듈

문제 설명


요 며칠 동안 Linux 핵을 공부할 때 사람을 미치게 하는 문제를 만났다. 문제는 다음과 같다. 핵 모듈을 작성할 때 코드에 오류가 발생했지만 컴파일러가 검사하지 않았다. 예를 들어 일부 메모리의 문제, 빈 바늘에 접근했다. 나는 실수로 NULL 바늘에 값을 부여하는 비교를 해서 insmod**에 부딪혔다.ko에서 오류가 발생하여 처음으로 KILL을 직접 알립니다.이유를 알 수 없을 때 두 번째 insmod가 막히니까 거기서 렉이 걸렸다고 해야겠죠.

문제 분석


코드 때문에 이 문제가 발생한 것은 슬프다. lsmod를 통해 불러온 모듈을 보면 이전에 insmod의 모듈이 존재했지만 마운트할 수 없고 인용 계수가 0이 되지 않았다.다시cat/proc/modules를 통해 이 모듈의 상태는loading이지 living이 아니라는 것을 알 수 있습니다.그래서 이 모듈을 마운트 해제하려면 이 두 가지를 수정하고 상태와 인용 계수를 0으로 수정해야 합니다.

문제 해결


문제를 찾아 분석하고 나면 문제를 해결하기 시작할 수 있다.수동 insmod를 통해 불러오는 모듈은 임시이기 때문에 리셋을 통해 상술한 문제를 해결할 수 있지만 매번 리셋할 수 없습니다. 따라서 insmod라는 모듈을 다시 작성하여 그 오류 모듈의 관련 속성을 수정합니다.커널 소스를 보면 struct module 구조에 포함된 다음 구성원이 표시됩니다.
struct module {
    enum module_state state; //     ,        
    char name[MODULE_NAME_LEN];   //     
    struct module_ref __percpu *refptr;   //       
}
enum module_state {
    MODULE_STATE_LIVE,  /* Normal state. */
    MODULE_STATE_COMING,    /* Full formed, running module_init. */
    MODULE_STATE_GOING, /* Going away. */
    MODULE_STATE_UNFORMED,  /* Still setting it up. */
};

우리는 상태와 인용 계수를 수정하면 된다.
  • 인용 계수 수정 아래 두 함수를 통해 int trymodule_get(struct module *);//module 인용 계수 증가void moduleput(struct module *);//모듈의 인용 계수 감소
  • 수정 상태는 모듈의 구성원state에 직접 값을 부여할 수 있습니다. 다음은 제가 쓴 테스트 코드입니다. 잔말 말고 코드를 붙여주세요
  • /*print_module.c*/
    #include
    #include
    #include
    #include
    
    MODULE_LICENSE("GPL");
    
    /*
    **                  
    **sudo cat /pro/kallsyms | grep [^_]modules$ 
    */
    #define MODULES 0xffffffff8ec5b470 
    /*          */
    #define DEBUG_MODULE 0 
    /*      */
    #define DEBUG 1  
    
    static char *name = "testtesttest";
    /*    ,         */
    module_param(name,charp,S_IRUGO); 
    
    static int __init print_module_init(void) 
    {
        struct list_head *module_head;
        struct list_head *pos;
        struct module *p;
        int i= 0;
        int ret;
        printk(KERN_INFO "print module init
    "
    ); module_head = (struct list_head*)MODULES; /* module*/ list_for_each(pos,module_head) { p = list_entry(pos,struct module,list); #if DEBUG #if DEBUG_MODULE /* , living, */ if(strcmp(p->name,name)==0){ p->state = MODULE_STATE_LIVE; if((ret = try_module_get(p)) == 0) { printk(KERN_ALERT "try_module_get error
    "
    ); } printk(KERN_INFO "%s ret is inc
    "
    ,p->name); } #else /* */ if(strcmp(p->name,name) == 0) { module_put(p); printk(KERN_INFO "%s ref is dec
    "
    ,p->name); } #endif #endif } return 0; } static void __exit print_module_exit(void) { printk(KERN_INFO "print module exit
    "
    ); } module_init(print_module_init); module_exit(print_module_exit);

    Makefile은 다음과 같습니다.
    obj-m:= print_module2.o
    
    KDIR:= /lib/modules/$(shell uname -r)/build
    
    all:
        $(MAKE) -C $(KDIR) M=$(shell pwd) modules
    clean:
        $(MAKE) -C $(KDIR) M=$(shell pwd) clean
    

    컴파일 통과 후 insmod printmodule.ko name=xxxx를 불러옵니다. xxx는 잘못된 모듈입니다. 그 과정에서 lsmod와cat/proc/modules를 통해 모듈 관련 정보를 볼 수 있습니다

    좋은 웹페이지 즐겨찾기