Fprobe is a function entry/exit probe mechanism in the Linux kernel, built on top of the ftrace framework. It allows developers to attach callbacks to function entry and exit points, similar to kprobes and kretprobes, but with improved performance for multiple functions through a single handler. This makes fprobe particularly useful for tracing and debugging kernel functions without the overhead associated with full ftrace features.
Key Features of Fprobe:
Performance: Provides faster instrumentation for multiple functions compared to traditional kprobes and kretprobes.
Structure: The fprobe structure includes fields for entry and exit handlers, allowing customized behavior when functions are entered or exited.
Registration: Fprobes can be registered using various methods, including function-name filters or direct address registration.
The usage of fprobe :
The fprobe is a wrapper of ftrace (+ kretprobe-like return callback) to attach callbacks to multiple function entry and exit. User needs to set up the struct fprobe and pass it to register_fprobe(). Typically, fprobe data structure is initialized with the entry_handler and/or exit_handler as below.
NOTE: callbacks refer to functions that are executed in response to specific events, particularly when a function is entered or exited
A typical fprobe setup might look like this:
struct fprobe fp = {
.entry_handler = my_entry_callback,
.exit_handler = my_exit_callback,
};
register_fprobe(&fp, "func*", "func2");
-----------------------------------------------------
#include <linux/kernel.h>
#include <linux/fprobe.h>
#include <linux/init.h>
// Function prototypes
int my_entry_callback(struct fprobe *fp, unsigned long entry_ip, unsigned long args, struct pt_regs *regs, void *data);
void my_exit_callback(struct fprobe *fp, unsigned long entry_ip, unsigned long args, struct pt_regs *regs, void *data);
void target_function(void); // Declare target_function prototype
// Define the fprobe structure
static struct fprobe fp = {
.entry_handler = my_entry_callback,
.exit_handler = my_exit_callback,
};
// The function we want to probe
void target_function(void) {
printk(KERN_INFO "Inside target_function\n");
}
// Entry callback
int my_entry_callback(struct fprobe *fp, unsigned long entry_ip, unsigned long args, struct pt_regs *regs, void *data) {
printk(KERN_INFO "Entered target_function\n");
return 0; // Return an int as expected
}
// Exit callback
void my_exit_callback(struct fprobe *fp, unsigned long entry_ip, unsigned long args, struct pt_regs *regs, void *data) {
printk(KERN_INFO "Exited target_function\n");
}
// Module initialization
static int __init my_module_init(void) {
// Register the fprobe for the target function
if (register_fprobe(&fp, "target_function", NULL)) {
printk(KERN_ERR "Failed to register fprobe\n");
return -1;
}
printk(KERN_INFO "Fprobe registered successfully\n");
// Call the target function to see the callbacks in action
target_function();
return 0;
}
// Module cleanup
static void __exit my_module_exit(void) {
// Unregister the fprobe
unregister_fprobe(&fp);
printk(KERN_INFO "Fprobe unregistered successfully\n");
}
module_init(my_module_init);
module_exit(my_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Fprobe Example Module");
MODULE_AUTHOR("SACHIN P BAPPALIGE");
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
make -C /lib/modules/6.12.0-rc2+/build M=/root/fprobe modules
make[1]: Entering directory '/root/linux'
CC [M] /root/fprobe/fprobe_example.o
MODPOST /root/fprobe/Module.symvers
CC [M] /root/fprobe/fprobe_example.mod.o
CC [M] /root/fprobe/.module-common.o
LD [M] /root/fprobe/fprobe_example.ko
BTF [M] /root/fprobe/fprobe_example.ko
make[1]: Leaving directory '/root/linux'
Step 3 : Insert module--> insmod fprobe_example.ko
Step 4: Check kernel logs with dmesg to see output from the callbacks.
Step 5: Remove the module using --> rmmod fprobe_example
Here’s a C program that demonstrates how to use fprobe to monitor the do_fork function in the Linux kernel. This example sets up entry and exit callbacks to log when the do_fork function is called and when it returns.
-------------------------------------
------------------------------------------------------------------------------
NOTE: Fprobe and kprobe are both mechanisms used in the Linux kernel for tracing and debugging, but they have distinct characteristics and use cases.
Kprobe :
Purpose: Kprobes allow developers to insert probes at almost any kernel function entry or exit point. They enable dynamic instrumentation by setting breakpoints on specified functions.
Structure: Each kprobe consists of a handler that is invoked when the probe is hit, allowing for custom actions or logging.
Performance: Kprobes can introduce overhead, especially when multiple probes are registered, as they rely on software breakpoints (SWBP) which can be slower compared to other methods.
Recursion Handling: Kprobes maintain a per-CPU variable (`current_kprobe`) to manage recursion safely, which prevents re-entry into the same probe handler.
No comments:
Post a Comment