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
// 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步: