linux内核模块内存检查器

时间:2014-04-17 02:49:34

标签: c linux kernel-module

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

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

  2. 如何使用sysfs创建一个允许用户查看内存泄漏摘要的只读文件?

  3. 这是我的代码到目前为止的样子

    // 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");
    

1 个答案:

答案 0 :(得分:0)

  

如何替换vmalloc和vfree   当我编译并运行我的模块任何内核模块分配和   释放内存会使用我的功能吗?

第1步。在调用vmalloc&amp;的文件中vfree,定义宏:

 #define vmalloc(x) profile_vmalloc(x)
 #define vfree(x) profile_vfree(x)

这将确保调用您的函数。

第2步:在profile_*函数的定义中,您是否会计并调用实际的vmalloc/vfree函数。

您已经在执行第2步,因此您只需要处理第1步。