我正在编写一个内核模块来监视一些想要在调用成功时将函数参数返回到user-land(通过netlink socket)的系统调用。
jprobe.kp.symbol_name = "rename";
jprobe.entry = rename_handler;
kretprobe.kp.symbol_name = "rename";
kretprobe.handler = rename_ret_handler;
static rename_obj_t _g_cur_rename = NULL;
static void _rename_handler(const char *oldpath, const char *newpath)
{
_g_cur_rename = create_rename(oldpath, newpath);
jprobe_return();
}
static void _rename_ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
/* Send only if successful */
if (regs_return_value(regs) == 0) {
add_send_queue(_g_cur_rename);
}
return 0;
}
我担心另一个重命名系统调用可以在jprobe之后抢占[1]当前的那个,我将发送错误的返回码和参数。
jprobe: rename(a, b)
jprobe rename(c, d)
kretprobe
kretprobe
编辑:本文[2]指出在kprobe处理程序期间禁用了中断。但这是否意味着在整个链中禁用中断(jprobe - > kprobe - > kretprobe)或仅针对该单个kprobe?
答案 0 :(得分:1)
每次jprobe
次呼叫都会禁用中断:不是整个序列。
在应用程序处理它们时,您期望多少次调用?根据您对调用的预期速度,有不同的方法。最简单的方法,如果您只需要几百个调用就可以处理它们,并且您将静态内存用于此目的,就是实现一个内存中的rename_obj_t
个对象的静态数组,然后使用内核中的atomic_add
asm包含指向下一个条目(修改数组的大小)。
这样,每次返回一个唯一的静态引用,只要计数器在处理返回的值之前没有回绕。保证atomic_add
具有正确的内存屏障,因此您不必担心缓存一致性等问题。