IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    kernel中统计ioctl

    Qiang发表于 2015-01-26 01:44:07
    love 0

    有个需求,要统计开机过程中所有的ioctl操作,用最简单最快的方式实现:直接修改vfs代码,在ioctl中加入统计代码,利用debugfs读取冲击信息:
    fs/ioctl.c:

    ?View Code C
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    
    //add for debug ioctl
    #include debugfs.h><span>
    #define ioc_record_size 80000    //record items
    struct record_data
    {
        u32 cmd;
        u32 pid;
        char process_name[16];
        char file_name[16];
    };
    static struct record_data ioc_datas[ioc_record_size] = {0};
    static u8 ioc_flag = 0; //0: not init; 1:runing; 2:stop
    static unsigned long ioc_data_offset = 0;
    spinlock_t ioc_lock;
     
    /*
     * When you add any new common ioctls to the switches above and below
     * please update compat_sys_ioctl() too.
     *
     * do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
     * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
     */
    int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
    	     unsigned long arg)
    {
    	int error = 0;
    	int __user *argp = (int __user *)arg;
    	struct inode *inode = file_inode(filp);
     
        //add for debug ioctl
        static struct dentry *ioc_debugfs_root;
        static struct debugfs_blob_wrapper ioc_data;
        static struct dentry *ioc_flag_entry;
        static struct dentry *ioc_data_entry;
     
        if(ioc_flag==0)
        {
            printk("========init ioc record========\n");
            spin_lock_init(&ioc_lock);
            ioc_debugfs_root = debugfs_create_dir("ioc_data", NULL);
    	    if (!ioc_debugfs_root)
    		    goto ioc_normal;
     
            ioc_flag_entry = debugfs_create_u8("flag", 0644, ioc_debugfs_root, &ioc_flag);
            if (!ioc_flag_entry)
            {
                printk("debugfs_create_u8 failed\n");
                debugfs_remove_recursive(ioc_debugfs_root);
    		    goto ioc_normal;
            }
     
            ioc_data.data = ioc_datas;
            ioc_data.size = ioc_record_size*sizeof(struct record_data);
            ioc_data_entry = debugfs_create_blob("data", 0644, ioc_debugfs_root, &ioc_data);
            if (!ioc_data_entry)
            {
                printk("debugfs_create_blob failed\n");
                debugfs_remove_recursive(ioc_debugfs_root);
                goto ioc_normal;
            }
            printk("========init ioc record OK========\n");
            ioc_flag = 1;
            ioc_data_offset = 0;
        }
     
        //printk(" [%d] %u\n", current->tgid, cmd);
        //record into memory
        if(ioc_flag==1)
        {
            spin_lock(&ioc_lock);
            if(ioc_data_offset < ioc_record_size)
            {
                ioc_datas[ioc_data_offset].cmd = cmd;
                ioc_datas[ioc_data_offset].pid = current->tgid;
                memcpy(ioc_datas[ioc_data_offset].process_name, current->comm, 16);
                memcpy(ioc_datas[ioc_data_offset].file_name, filp->f_path.dentry->d_iname, 16);
                ioc_data_offset++;
            }
            spin_unlock(&ioc_lock);
        }
    ioc_normal:

    其中记录了被打开的文件,进行操作的线程名,操作的进程组pid以及cmd。
    进入shell,再拿到统计数据:

    ?View Code BASH
    1
    2
    3
    
    mount -t debugfs none /sys/kernel/debug/
    cat /sys/kernel/debug/ioc_data/data > /tmp/dd
    ps ax > /tmp/ps

    最后通过一个小程序解析拿到的数据:

    ?View Code C
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    
    #include 
     
    char procname[65535][1024]= {0};
     
    struct record_data
    {
        unsigned int cmd;
        unsigned int pid;
        char process_name[16];
        char file_name[16];
    };
     
    main(int argc, char **argv)
    {
    	unsigned int line = 0;
    	int pid, i;
    	int fd = open("dd",O_RDWR);
     
    	char psbuf[1024] = {0};
    	while(gets(psbuf))
    	{
    		i = 0;
    		pid = atoi(psbuf);
    		while(psbuf[i]!=' ') i++;
    		strcpy(procname[pid], psbuf+i+1);
    		memset(psbuf, 0, 1024);
    	}
     
    	struct record_data record = {0};
    	while(read(fd, &record, sizeof(struct record_data)) == sizeof(struct record_data)&& record.pid)
    	{
    		printf("%08d %16s 0x%08x %16s %s\n", line++, record.file_name, record.cmd, record.process_name, procname[record.pid][0]?procname[record.pid]:"UNKNOW");
    		memset(&record, 0 , sizeof(struct record_data));
    	}
    }
    ?View Code BASH
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    rm -rf pps
    cat ps | while read line2
    do
    	pid=`echo $line2 | awk '{print $1}'`
    	name=`echo $line2 | awk '{print $5}'`
    	echo $pid $name >> pps
    done
     
    cat pps | ./a.out


沪ICP备19023445号-2号
友情链接