注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

火车的家

Put first thing first

 
 
 

日志

 
 

2016.05.28 linux kernel 添加 sys 虚拟文件系统节点  

2016-05-28 21:46:08|  分类: linux kernel |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

下面是一份简单的驱动范本,实现了/sys/class/my/profiler/memleaks,/sys/class/my/profiler/scan_end_addr,/sys/class/my/profiler/scan_start_addr三个节点。/sys/class/my/profiler/memleaks可读,其余两个可写。

#include <linux/pci.h>
#include <linux/fs.h>
#include <linux/kprobes.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/pagemap.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/version.h>
#include <linux/device.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/signal.h>
#include <linux/module.h>
#include "my_kmp.h"

static struct class *my_kmp_class = NULL;
static struct device *my_kmp_dev = NULL;
static unsigned int start_addr = 0;
static unsigned int end_addr = 0;

//返回值是buf的size
static ssize_t my_memleaks_show(struct device *dev, struct device_attribute *attr, char *buf)
{
       int size = 0, len = 0;
       struct my_kmp_track_info *e_addr, *e_caller;

       list_for_each_entry(e_addr, &my_mem_stats, link) {
               if ( (unsigned int)e_addr->addr <= end_addr && (unsigned int)e_addr->addr >= start_addr ) {
                       int count = 0;

                       list_for_each_entry(e_caller, &my_mem_stats, link) {
                               if ( e_caller->caller == e_addr->caller ) {
                                       count++;
                               }
                       }

                       if ( count == 1 ) {
                               size = sprintf(buf+len, "0x%08x:%s:0x%08x\n", (int)e_addr->addr, "Not freed yet", (int)e_addr->caller);
                       } else {
                               size = sprintf(buf+len, "0x%08x:%s:0x%08x\n", (int)e_addr->addr, "possible leak", (int)e_addr->caller);
                       }

                       len += size;
               }
       }

       if ( len == 0 ) {
               len = sprintf(buf, "There aren't any addresses in the range 0x%08x - 0x%08x\n", start_addr, end_addr );
       }

       return len;
}

static ssize_t my_scan_start_addr_store(struct device *dev,
               struct device_attribute *attr,
               const char *buf, size_t count)
{
       int val;

       if (sscanf(buf, "0x%08x", &val) != 1)
               return -EINVAL;

       start_addr = val;

       return count;
}

static ssize_t my_scan_end_addr_store(struct device *dev,
               struct device_attribute *attr,
               const char *buf, size_t count)
{
       int val;

       if (sscanf(buf, "0x%08x", &val) != 1)
               return -EINVAL;

       end_addr = val;

       return count;
}

static DEVICE_ATTR(memleaks, 0444, my_memleaks_show, NULL);
static DEVICE_ATTR(scan_start_addr, 0222, NULL, my_scan_start_addr_store);
static DEVICE_ATTR(scan_end_addr, 0222, NULL, my_scan_end_addr_store);

int my_kmp_init(void)
{
       int ret = 0;

       printk("kmp init start\n");

       my_kmp_class = class_create(THIS_MODULE, "my");
       if (unlikely(IS_ERR(my_kmp_class))) {
               printk(KERN_ERR "failed to allocate class.\n");
               return PTR_ERR(my_kmp_class);
       }

       my_kmp_dev = device_create(my_kmp_class, NULL, 0, NULL, "profiler");
       if (unlikely(IS_ERR(my_kmp_dev))) {
               printk(KERN_ERR "failed to allocate device.\n");
               class_destroy(my_kmp_class);
               return PTR_ERR(my_kmp_dev);
       }

       ret = device_create_file(my_kmp_dev, &dev_attr_memleaks);
       if (unlikely(ret)) {
               printk(KERN_ERR "failed to create device file.\n");
               class_destroy(my_kmp_class);
               device_destroy(my_kmp_class, 0);
               return -1;
       }

       ret = device_create_file(my_kmp_dev, &dev_attr_scan_start_addr);
       if (unlikely(ret)) {
               printk(KERN_ERR "failed to create device file.\n");
               class_destroy(my_kmp_class);
               device_destroy(my_kmp_class, 0);
               return -1;
       }

       ret = device_create_file(my_kmp_dev, &dev_attr_scan_end_addr);
       if (unlikely(ret)) {
               printk(KERN_ERR "failed to create device file.\n");
               class_destroy(my_kmp_class);
               device_destroy(my_kmp_class, 0);
               return -1;
       }

       printk("kmp init done.\n");
       return 0;
}

void my_kmp_exit(void)
{
       printk("kmp exit.\n");

       device_remove_file(my_kmp_dev, &dev_attr_memleaks);
       device_remove_file(my_kmp_dev, &dev_attr_scan_start_addr);
       device_remove_file(my_kmp_dev, &dev_attr_scan_end_addr);

       device_destroy(my_kmp_class, 0);

       class_destroy(my_kmp_class);
}

module_init(my_kmp_init);
module_exit(my_kmp_exit);

MODULE_AUTHOR("Graham Ge");
MODULE_LICENSE("GPL");
  评论这张
 
阅读(19)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017