关于kprobe的几种使用

1:探测schedule()函数,在探测点执行前后分别输出当前正在运行的进程、所在的CPU以及preempt_count(),当卸载该模块时将输出该模块运行时间以及发生的调度次数


/* kprobe-exam.c */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/kallsyms.h>
#include <linux/sched.h>
#include <linux/time.h>

static struct kprobe kp;
static struct timeval start, end;
static int schedule_counter = 0;

int handler_pre(struct kprobe *p, struct pt_regs *regs)
{
    printk("current task on CPU#%d: %s (before scheduling), preempt_count = %d\n", smp_processor_id(), current->comm, preempt_count());
    schedule_counter++;
    return 0;
}

void handler_post(struct kprobe *p, struct pt_regs *regs, unsigned long flags)
{
    printk("current task on CPU#%d: %s (after scheduling), preempt_count = %d\n", smp_processor_id(), current->comm, preempt_count());
}

int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr)
{
    printk("A fault happened during probing.\n");
    return 0;
}

int init_module(void)
{
    int ret;

    kp.pre_handler = handler_pre;
    kp.post_handler = handler_post;
    kp.fault_handler = handler_fault;
    kp.addr = (kprobe_opcode_t*) kallsyms_lookup_name("schedule");
    
    if (!kp.addr) {
        printk("Couldn't get the address of schedule.\n");
        return -1;
    }

    if ((ret = register_kprobe(&kp) < 0)) {
        printk("register_kprobe failed, returned %d\n", ret);
        return -1;
    }

    do_gettimeofday(&start);

    printk("kprobe registered\n");
    return 0;
}

void cleanup_module(void)
{
    unregister_kprobe(&kp);
    do_gettimeofday(&end);
    printk("Scheduling times is %d during of %ld milliseconds.\n", schedule_counter, ((end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec))/1000);
    printk("kprobe unregistered\n");
}

MODULE_LICENSE("GPL");

2:,它示例了获取系统调用open的参数,但读者不要试图在实际的应用中这么使用,因为copy_from_user可能导致睡眠,而kprobe并不允许在探测点处理函数中这么做

/* jprobe-exam.c */
/* jprobe-exam.c */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/kallsyms.h>
#include <linux/fs.h>
#include <asm/uaccess.h>


static struct jprobe jp;

asmlinkage long jprobe_sys_open(const char __user *filename, int flags, int mode)
{
    int len = PATH_MAX;
    char * tmpfilename = NULL;

    if (TASK_SIZE - (unsigned long) filename < PATH_MAX) {
        len = TASK_SIZE - (unsigned long) filename;
    }

    tmpfilename = kmalloc(len, GFP_ATOMIC);
    if (tmpfilename == NULL) return 0;

    if (copy_from_user(tmpfilename, filename, len)) return 0;

    printk("process '%s' call open('%s', %d, %d)\n", current->comm, tmpfilename, flags, mode);
    jprobe_return();
    return 0;
}

int init_module(void)
{
    int ret;

    jp.entry = (kprobe_opcode_t *) jprobe_sys_open;
    jp.kp.addr = (kprobe_opcode_t *)kallsyms_lookup_name("sys_open");
    if (!jp.kp.addr) {
        printk("Couldn't find the address of sys_open\n");
        return -1;
    }

    if ((ret = register_jprobe(&jp)) <0) {
        printk("register_jprobe failed, returned %d\n", ret);
        return -1;
    }
    printk("Registered a jprobe.\n");
    return 0;
}

void cleanup_module(void)
{
    unregister_jprobe(&jp);
    printk("jprobe unregistered\n");
}

MODULE_LICENSE("GPL");

3:kretprobe-exam.c是一个返回探测例子,它探测系统调用open并输出返回值小于0的情况。它也有意设置maxactive为1,以便示例丢失探测运行的情况,当然,只有系统并发运行多个sys_open才可能导致这种情况,因此,读者需要有SMP的系统或者有超线程支持才能看到这种情况。

/*kretprobe-exam.c*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/kallsyms.h>

static struct kretprobe kretp;

static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
    // Substitute the appropriate register name for your architecture --
    // e.g., regs->rax for x86_64, regs->gpr[3] for ppc64.
    int retval = (int) regs->eax;
    if (retval < 0) {
        printk("sys_open returns %d\n", retval);
    }
    return 0;
}

int init_module(void)
{
    int ret;

    kretp.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("sys_open");
    if (!kretp.kp.addr) {
        printk("Couldn't find sys_open.\n");
        return -1;
    }

    kretp.handler = ret_handler,
    kretp.maxactive = 1;

    if ((ret = register_kretprobe(&kretp)) < 0) {
        printk("register_kretprobe failed, returned %d\n", ret);
        return -1;
    }
    printk("Registered a return probe.\n");
    return 0;
}

void cleanup_module(void)
{
    unregister_kretprobe(&kretp);
    printk("kretprobe unregistered\n");
    printk("Missed %d sys_open probe instances.\n", kretp.nmissed);
}

MODULE_LICENSE("GPL");



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值