C linux内核模块内存检查器

C linux内核模块内存检查器,c,linux,kernel-module,C,Linux,Kernel Module,我正在开发一个内核内存检查器来查找内核空间中的内存泄漏 我有两个函数profile_vmalloc和profile_vfree,profile_vmalloc使用vmalloc分配内存并将内存分配的信息添加到列表中,profile_vfree释放分配的内存并从列表中删除该信息。如何替换vmalloc和vfree,以便在编译和运行模块时,任何分配和释放内存的内核模块都将使用我的函数 如何使用sysfs创建一个只读文件,使用户可以查看内存泄漏摘要 到目前为止,我的代码就是这样的 // Linux K

我正在开发一个内核内存检查器来查找内核空间中的内存泄漏

  • 我有两个函数profile_vmalloc和profile_vfree,profile_vmalloc使用vmalloc分配内存并将内存分配的信息添加到列表中,profile_vfree释放分配的内存并从列表中删除该信息。如何替换vmalloc和vfree,以便在编译和运行模块时,任何分配和释放内存的内核模块都将使用我的函数

  • 如何使用sysfs创建一个只读文件,使用户可以查看内存泄漏摘要

  • 到目前为止,我的代码就是这样的

    // Linux Kernel headers
    #include    <linux/module.h>
    #include    <linux/kernel.h>
    #include    <linux/init.h>
    #include    <linux/config.h>
    #include    <linux/vmalloc.h>
    
    #define  FILE_NAME_LENGTH          256
    #define  vmalloc(size)              profile_malloc (block_size, __FILE__, __LINE__)
    #define  vfree(mem_ref)                 profile_free(mem_ref)
    
    struct _MEM_INFO
    {
        const void          *address;
        size_t              size;
        char                file_name[FILE_NAME_LENGTH];
        size_t              length;
    };
    typedef struct _MEM_INFO MEM_INFO;
    
    struct _MEM_LEAK {
        MEM_INFO mem_info;
        struct _MEM_LEAK * next;
    };
    typedef struct _MEM_LEAK MEM_LEAK;
    
    
    
    #undef      vmalloc
    #undef      vfree
    
    
    static MEM_PROFILER_LIST * ptr_start = NULL;
    static MEM_PROFILER_LIST * ptr_next =  NULL;
    
    /*
     * adds allocated memory info. into the list
     *
     */
    void add(MEM_INFO alloc_info)
    {
    
        MEM_PROFILER_LIST * mem_leak_info = NULL;
        mem_leak_info = (MEM_PROFILER_LIST *) malloc (sizeof(MEM_PROFILER_LIST));
        mem_leak_info->mem_info.address = alloc_info.address;
        mem_leak_info->mem_info.size = alloc_info.size;
        strcpy(mem_leak_info->mem_info.file_name, alloc_info.file_name); 
        mem_leak_info->mem_info.line = alloc_info.line;
        mem_leak_info->next = NULL;
    
        if (ptr_start == NULL)  
        {
            ptr_start = mem_leak_info;
            ptr_next = ptr_start;
        }
        else {
            ptr_next->next = mem_leak_info;
            ptr_next = ptr_next->next;              
        }
    
    }
    
    /*
     * remove memory info. from the list
     *
     */
    void erase(unsigned pos)
    {
    
        unsigned int i = 0;
        MEM_PROFILER_LIST * alloc_info, * temp;
    
        if(pos == 0)
        {
            MEM_PROFILER_LIST * temp = ptr_start;
            ptr_start = ptr_start->next;
            free(temp);
        }
        else 
        {
            for(i = 0, alloc_info = ptr_start; i < pos; 
                alloc_info = alloc_info->next, ++i)
            {
                if(pos == i + 1)
                {
                    temp = alloc_info->next;
                    alloc_info->next =  temp->next;
                    free(temp);
                    break;
                }
            }
        }
    }
    
    /*
     * deletes all the elements from the list
     */
    void clear()
    {
        MEM_PROFILER_LIST * temp = ptr_start;
        MEM_PROFILER_LIST * alloc_info = ptr_start;
    
        while(alloc_info != NULL) 
        {
            alloc_info = alloc_info->next;
            free(temp);
            temp = alloc_info;
        }
    }
    
    /*
     * profile of vmalloc
     */
    void * profile_vmalloc (unsigned int size, const char * file, unsigned int line)
    {
        void * ptr = vmalloc (size);
        if (ptr != NULL) 
        {
            add_mem_info(ptr, size, file, line);
        }
        return ptr;
    }
    
    
    /*
     * profile of free
     */
    void profile_free(void * mem_ref)
    {
        remove_mem_info(mem_ref);
        free(mem_ref);
    }
    
    /*
     * gets the allocated memory info and adds it to a list
     *
     */
    void add_mem_info (void * mem_ref, unsigned int size,  const char * file, unsigned int line)
    {
        MEM_INFO mem_alloc_info;
    
        /* fill up the structure with all info */
        memset( &mem_alloc_info, 0, sizeof ( mem_alloc_info ) );
        mem_alloc_info.address  = mem_ref;
        mem_alloc_info.size = size;
        strncpy(mem_alloc_info.file_name, file, FILE_NAME_LENGTH);
        mem_alloc_info.line = line;
    
        /* add the above info to a list */
        add(mem_alloc_info);
    }
    
    /*
     * if the allocated memory info is part of the list, removes it
     *
     */
    void remove_mem_info (void * mem_ref)
    {
        unsigned int i;
        MEM_PROFILER_LIST  * leak_info = ptr_start;
    
        /* check if allocate memory is in our list */
        for(i = 0; leak_info != NULL; ++i, leak_info = leak_info->next)
        {
            if ( leak_info->mem_info.address == mem_ref )
            {
                erase ( i );
                break;
            }
        }
    }
    
    /*
     * writes a memory leak summary to a file
     */
    void mem_leak_summary(void)
    {
        unsigned int i;
        MEM_PROFILER_LIST * mem_output;
    
        FILE * fp_write = fopen (SUMMARY_FILE, "wt");
        char info[1024];
    
        if(fp_write != NULL)
        {
    
            fwrite(info, (strlen(info) + 1) , 1, fp_write);
            sprintf(info, "%s\n", "-----------------------------------");   
            fwrite(info, (strlen(info) + 1) , 1, fp_write);
    
            for(mem_output= ptr_start; mem_output!= NULL; mem_output= mem_output->next)
            {
                sprintf(info, "address : %d\n", leak_info->mem_output.address);
                fwrite(info, (strlen(info) + 1) , 1, fp_write);
                sprintf(info, "size    : %d bytes\n", leak_info->mem_output.size);          
                fwrite(info, (strlen(info) + 1) , 1, fp_write);
                sprintf(info, "line    : %d\n", leak_info->mem_output.line);
                fwrite(info, (strlen(info) + 1) , 1, fp_write);
                sprintf(info, "%s\n", "-----------------------------------");   
                fwrite(info, (strlen(info) + 1) , 1, fp_write);
            }
        }   
        clear();
    }
    
    static int __init profiler_init(void)
    {
        return 0;
    }
    
    static void __exit profiler_cleanup(void)
    {
        printk("profiler module uninstalled\n");
    }
    
    module_init(profiler_init);
    module_exit(profiler_cleanup);
    MODULE_LICENSE("GPL");
    
    //Linux内核头
    #包括
    #包括
    #包括
    #包括
    #包括
    #定义文件名长度256
    #定义vmalloc(大小)配置文件\u malloc(块大小、文件大小、行大小)
    #定义vfree(mem\u ref)profile\u free(mem\u ref)
    结构成员信息
    {
    const void*地址;
    大小;
    字符文件名[文件名长度];
    尺寸与长度;
    };
    typedef struct_MEM_INFO MEM_INFO;
    结构内存泄漏{
    MEM_INFO MEM_INFO;
    结构内存泄漏*下一步;
    };
    typedef struct_MEM_LEAK MEM_LEAK;
    #未定义vmalloc
    #未定义vfree
    静态MEM_PROFILER_LIST*ptr_start=NULL;
    静态MEM_PROFILER_LIST*ptr_next=NULL;
    /*
    *添加分配的内存信息。列入名单
    *
    */
    无效添加(成员信息分配信息)
    {
    MEM_PROFILER_LIST*MEM_leak_info=NULL;
    mem_leak_info=(mem_PROFILER_LIST*)malloc(sizeof(mem_PROFILER_LIST));
    mem_leak_info->mem_info.address=alloc_info.address;
    mem_leak_info->mem_info.size=alloc_info.size;
    strcpy(mem\u leak\u info->mem\u info.file\u name、alloc\u info.file\u name);
    mem_leak_info->mem_info.line=alloc_info.line;
    mem_leak_info->next=NULL;
    如果(ptr_start==NULL)
    {
    ptr_start=mem_leak_info;
    ptr_next=ptr_start;
    }
    否则{
    ptr\u next->next=mem\u leak\u info;
    ptr_next=ptr_next->next;
    }
    }
    /*
    *删除内存信息。从名单上
    *
    */
    无效擦除(未签名pos)
    {
    无符号整数i=0;
    MEM_PROFILER_列表*分配信息,*临时;
    如果(位置==0)
    {
    MEM_PROFILER_LIST*temp=ptr_start;
    ptr_开始=ptr_开始->下一步;
    免费(临时);
    }
    其他的
    {
    对于(i=0,alloc_info=ptr_start;i下一步,++i)
    {
    如果(位置==i+1)
    {
    温度=分配信息->下一步;
    分配信息->下一步=临时->下一步;
    免费(临时);
    打破
    }
    }
    }
    }
    /*
    *从列表中删除所有元素
    */
    无效清除()
    {
    MEM_PROFILER_LIST*temp=ptr_start;
    MEM_PROFILER_LIST*alloc_info=ptr_start;
    while(alloc_info!=NULL)
    {
    alloc\u info=alloc\u info->next;
    免费(临时);
    温度=分配信息;
    }
    }
    /*
    *vmalloc简介
    */
    void*profile_vmalloc(无符号整数大小、常量字符*文件、无符号整数行)
    {
    void*ptr=vmalloc(尺寸);
    如果(ptr!=NULL)
    {
    添加内存信息(ptr、大小、文件、行);
    }
    返回ptr;
    }
    /*
    *自由市场概况
    */
    无效剖面图(无效*内存参考)
    {
    删除记忆信息(记忆参考);
    免费(mem_ref);
    }
    /*
    *获取分配的内存信息并将其添加到列表中
    *
    */
    void add_mem_info(void*mem_ref,无符号整数大小,常量字符*文件,无符号整数行)
    {
    MEM_INFO MEM_alloc_INFO;
    /*用所有信息填充结构*/
    memset(&mem_alloc_info,0,sizeof(mem_alloc_info));
    mem_alloc_info.address=mem_ref;
    mem_alloc_info.size=大小;
    strncpy(mem_alloc_info.file_name、file、file_name_LENGTH);
    mem_alloc_info.line=行;
    /*将上述信息添加到列表中*/
    添加(成员分配信息);
    }
    /*
    *如果分配的内存信息是列表的一部分,则将其删除
    *
    */
    无效删除成员信息(无效*成员参考)
    {
    无符号整数i;
    MEM_PROFILER_LIST*leak_info=ptr_start;
    /*检查分配内存是否在我们的列表中*/
    对于(i=0;泄漏信息!=NULL;++i,泄漏信息=泄漏信息->下一步)
    {
    如果(泄漏信息->内存信息地址==内存参考)
    {
    删除(i);
    打破
    }
    }
    }
    /*
    *将内存泄漏摘要写入文件
    */
    作废文件泄漏汇总表(作废)
    {
    无符号整数i;
    内存分析器列表*内存输出;
    文件*fp_write=fopen(摘要文件,“wt”);
    字符信息[1024];
    if(fp_write!=NULL)
    {
    fwrite(info,(strlen(info)+1),1,fp_write;
    sprintf(信息,“%s\n”,“-----------------------------------------”;
    fwrite(info,(strlen(info)+1),1,fp_write;
    for(mem_output=ptr_start;mem_output!=NULL;mem_output=mem_output->next)
    {
    sprintf(信息,“地址:%d\n”,泄漏信息->内存输出地址);
    fwrite(info,(strlen(info)+1),1,fp_write;
    sprintf(信息,“大小:%d字节\n”,泄漏信息->内存输出.size);
    fwrite(info,(strlen(info)+1),1,fp_write;
    sprintf(信息,“行:%d\n”,泄漏信息->内存输出.line);
    fwrite(info,(strlen(info)+1),1,fp_write;
    sprintf(信息,“%s\n”,“-----------------------------------------”;
    fwrite(info,(strlen(info)+1),1,fp_write;
    }
    }   
    清除();
    }
    静态int\uu init探查器\u init(void)
    {
    返回0;
    }
    静态无效\uuu退出探查器\u清理(无效)
    {
    printk(“已卸载探查器模块\n”);
    }
    模块_init(探查器_init);
    模块退出(探查器清理);
    模块许可证(“GPL”);
    
    如何替换vmalloc和vfree so 当我编译和运行我的模块时,任何内核模块 释放内存将使用我的功能

    步骤1。在调用
    vmalloc
    vfree
    的文件中,定义宏:

     #define vmalloc(x) profile_vmalloc(x)
     #define vfree(x) profile_vfree(x)
    
    这将确保调用您的函数

    第2步: