mirror of
https://github.com/gatieme/LDD-LinuxDeviceDrivers.git
synced 2026-09-24 05:53:54 +08:00
增加了cgroup的学习文档...
This commit is contained in:
@@ -0,0 +1 @@
|
||||
cmd_/home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/driver/probe/test.ko := ld -r -m elf_x86_64 -T ./scripts/module-common.lds --build-id -o /home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/driver/probe/test.ko /home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/driver/probe/test.o /home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/driver/probe/test.mod.o
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
/home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/driver/probe/test.ko
|
||||
/home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/driver/probe/test.o
|
||||
@@ -0,0 +1,78 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
#
|
||||
# Makefile for the LDD-LinuxDeviceDrivers.
|
||||
#
|
||||
# Author: gatieme
|
||||
# Create: 2016-07-29 15:50:46
|
||||
# Last modified: 2016-07-29 16:10:29
|
||||
# Description:
|
||||
# This program is loaded as a kernel(v2.6.18 or later) module.
|
||||
# Use "make install" to load it into kernel.
|
||||
# Use "make remove" to remove the module out of kernel.
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
ROOT=..
|
||||
#PLATFORM=$(shell $(ROOT)/systype.sh)
|
||||
#include $(ROOT)/Make.defines.$(PLATFORM)
|
||||
|
||||
# my driver description
|
||||
DRIVER_VERSION := "1.0.0"
|
||||
DRIVER_AUTHOR := "Gatieme @ AderStep Inc..."
|
||||
DRIVER_DESC := "Linux input module for Elo MultiTouch(MT) devices"
|
||||
DRIVER_LICENSE := "Dual BSD/GPL"
|
||||
|
||||
|
||||
MODULE_NAME := test
|
||||
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
|
||||
#CFG_FLAGS += -O2 -I./
|
||||
#EXTRA_CFLAGS += $(C_FLAGS) $(CFG_INC) $(CFG_INC)
|
||||
|
||||
|
||||
|
||||
obj-m := $(MODULE_NAME).o #print_vmarea.o
|
||||
|
||||
else
|
||||
|
||||
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
|
||||
PWD := $(shell pwd)
|
||||
|
||||
modules:
|
||||
make -C $(KERNELDIR) M=$(PWD) modules
|
||||
|
||||
modules_install:
|
||||
make -C $(KERNELDIR) M=$(PWD) modules_install
|
||||
|
||||
|
||||
|
||||
insmod:
|
||||
sudo insmod $(MODULE_NAME).ko
|
||||
|
||||
reinsmod:
|
||||
sudo rmmod $(MODULE_NAME)
|
||||
sudo insmod $(MODULE_NAME).ko
|
||||
|
||||
github:
|
||||
cd $(ROOT) && make github
|
||||
|
||||
rmmod:
|
||||
sudo rmmod $(MODULE_NAME)
|
||||
|
||||
test :
|
||||
sudo ../injector/memInjector -l stack -m random -t word_0 --time 1 --timeout 3 -p 1
|
||||
|
||||
clean:
|
||||
make -C $(KERNELDIR) M=$(PWD) clean
|
||||
rm -f modules.order Module.symvers Module.markers
|
||||
|
||||
.PHNOY:
|
||||
modules modules_install clean
|
||||
|
||||
|
||||
|
||||
endif
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
cmd_/home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/driver/probe/jprobe/jprobe-exam.ko := ld -r -m elf_x86_64 -T ./scripts/module-common.lds --build-id -o /home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/driver/probe/jprobe/jprobe-exam.ko /home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/driver/probe/jprobe/jprobe-exam.o /home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/driver/probe/jprobe/jprobe-exam.mod.o
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
/home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/driver/probe/jprobe/jprobe-exam.ko
|
||||
/home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/driver/probe/jprobe/jprobe-exam.o
|
||||
@@ -0,0 +1,78 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
#
|
||||
# Makefile for the LDD-LinuxDeviceDrivers.
|
||||
#
|
||||
# Author: gatieme
|
||||
# Create: 2016-07-29 15:50:46
|
||||
# Last modified: 2016-07-29 16:10:29
|
||||
# Description:
|
||||
# This program is loaded as a kernel(v2.6.18 or later) module.
|
||||
# Use "make install" to load it into kernel.
|
||||
# Use "make remove" to remove the module out of kernel.
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
ROOT=..
|
||||
#PLATFORM=$(shell $(ROOT)/systype.sh)
|
||||
#include $(ROOT)/Make.defines.$(PLATFORM)
|
||||
|
||||
# my driver description
|
||||
DRIVER_VERSION := "1.0.0"
|
||||
DRIVER_AUTHOR := "Gatieme @ AderStep Inc..."
|
||||
DRIVER_DESC := "Linux input module for Elo MultiTouch(MT) devices"
|
||||
DRIVER_LICENSE := "Dual BSD/GPL"
|
||||
|
||||
|
||||
MODULE_NAME := jprobe-exam
|
||||
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
|
||||
#CFG_FLAGS += -O2 -I./
|
||||
#EXTRA_CFLAGS += $(C_FLAGS) $(CFG_INC) $(CFG_INC)
|
||||
|
||||
|
||||
|
||||
obj-m := $(MODULE_NAME).o #print_vmarea.o
|
||||
|
||||
else
|
||||
|
||||
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
|
||||
PWD := $(shell pwd)
|
||||
|
||||
modules:
|
||||
make -C $(KERNELDIR) M=$(PWD) modules
|
||||
|
||||
modules_install:
|
||||
make -C $(KERNELDIR) M=$(PWD) modules_install
|
||||
|
||||
|
||||
|
||||
insmod:
|
||||
sudo insmod $(MODULE_NAME).ko
|
||||
|
||||
reinsmod:
|
||||
sudo rmmod $(MODULE_NAME)
|
||||
sudo insmod $(MODULE_NAME).ko
|
||||
|
||||
github:
|
||||
cd $(ROOT) && make github
|
||||
|
||||
rmmod:
|
||||
sudo rmmod $(MODULE_NAME)
|
||||
|
||||
test :
|
||||
sudo ../injector/memInjector -l stack -m random -t word_0 --time 1 --timeout 3 -p 1
|
||||
|
||||
clean:
|
||||
make -C $(KERNELDIR) M=$(PWD) clean
|
||||
rm -f modules.order Module.symvers Module.markers
|
||||
|
||||
.PHNOY:
|
||||
modules modules_install clean
|
||||
|
||||
|
||||
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/* 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>
|
||||
#include <linux/slab.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");
|
||||
@@ -0,0 +1,39 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/vermagic.h>
|
||||
#include <linux/compiler.h>
|
||||
|
||||
MODULE_INFO(vermagic, VERMAGIC_STRING);
|
||||
|
||||
__visible struct module __this_module
|
||||
__attribute__((section(".gnu.linkonce.this_module"))) = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.init = init_module,
|
||||
#ifdef CONFIG_MODULE_UNLOAD
|
||||
.exit = cleanup_module,
|
||||
#endif
|
||||
.arch = MODULE_ARCH_INIT,
|
||||
};
|
||||
|
||||
static const struct modversion_info ____versions[]
|
||||
__used
|
||||
__attribute__((section("__versions"))) = {
|
||||
{ 0xcd71858e, __VMLINUX_SYMBOL_STR(module_layout) },
|
||||
{ 0xe16b0d30, __VMLINUX_SYMBOL_STR(unregister_jprobe) },
|
||||
{ 0xb1bedeb7, __VMLINUX_SYMBOL_STR(register_jprobe) },
|
||||
{ 0xe007de41, __VMLINUX_SYMBOL_STR(kallsyms_lookup_name) },
|
||||
{ 0x1b9aca3f, __VMLINUX_SYMBOL_STR(jprobe_return) },
|
||||
{ 0x27e1a049, __VMLINUX_SYMBOL_STR(printk) },
|
||||
{ 0x4f6b400b, __VMLINUX_SYMBOL_STR(_copy_from_user) },
|
||||
{ 0xd2b09ce5, __VMLINUX_SYMBOL_STR(__kmalloc) },
|
||||
{ 0x8bdd5b5d, __VMLINUX_SYMBOL_STR(current_task) },
|
||||
{ 0x3356b90b, __VMLINUX_SYMBOL_STR(cpu_tss) },
|
||||
{ 0xbdfb6dbb, __VMLINUX_SYMBOL_STR(__fentry__) },
|
||||
};
|
||||
|
||||
static const char __module_depends[]
|
||||
__used
|
||||
__attribute__((section(".modinfo"))) =
|
||||
"depends=";
|
||||
|
||||
|
||||
MODULE_INFO(srcversion, "D5690A5FB79FCF9F6F9F059");
|
||||
@@ -0,0 +1 @@
|
||||
kernel//home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/driver/probe/jprobe/jprobe-exam.ko
|
||||
@@ -0,0 +1,78 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
#
|
||||
# Makefile for the LDD-LinuxDeviceDrivers.
|
||||
#
|
||||
# Author: gatieme
|
||||
# Create: 2016-07-29 15:50:46
|
||||
# Last modified: 2016-07-29 16:10:29
|
||||
# Description:
|
||||
# This program is loaded as a kernel(v2.6.18 or later) module.
|
||||
# Use "make install" to load it into kernel.
|
||||
# Use "make remove" to remove the module out of kernel.
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
ROOT=..
|
||||
#PLATFORM=$(shell $(ROOT)/systype.sh)
|
||||
#include $(ROOT)/Make.defines.$(PLATFORM)
|
||||
|
||||
# my driver description
|
||||
DRIVER_VERSION := "1.0.0"
|
||||
DRIVER_AUTHOR := "Gatieme @ AderStep Inc..."
|
||||
DRIVER_DESC := "Linux input module for Elo MultiTouch(MT) devices"
|
||||
DRIVER_LICENSE := "Dual BSD/GPL"
|
||||
|
||||
|
||||
MODULE_NAME := kprobe-exam
|
||||
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
|
||||
#CFG_FLAGS += -O2 -I./
|
||||
#EXTRA_CFLAGS += $(C_FLAGS) $(CFG_INC) $(CFG_INC)
|
||||
|
||||
|
||||
|
||||
obj-m := $(MODULE_NAME).o #print_vmarea.o
|
||||
|
||||
else
|
||||
|
||||
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
|
||||
PWD := $(shell pwd)
|
||||
|
||||
modules:
|
||||
make -C $(KERNELDIR) M=$(PWD) modules
|
||||
|
||||
modules_install:
|
||||
make -C $(KERNELDIR) M=$(PWD) modules_install
|
||||
|
||||
|
||||
|
||||
insmod:
|
||||
sudo insmod $(MODULE_NAME).ko
|
||||
|
||||
reinsmod:
|
||||
sudo rmmod $(MODULE_NAME)
|
||||
sudo insmod $(MODULE_NAME).ko
|
||||
|
||||
github:
|
||||
cd $(ROOT) && make github
|
||||
|
||||
rmmod:
|
||||
sudo rmmod $(MODULE_NAME)
|
||||
|
||||
test :
|
||||
sudo ../injector/memInjector -l stack -m random -t word_0 --time 1 --timeout 3 -p 1
|
||||
|
||||
clean:
|
||||
make -C $(KERNELDIR) M=$(PWD) clean
|
||||
rm -f modules.order Module.symvers Module.markers
|
||||
|
||||
.PHNOY:
|
||||
modules modules_install clean
|
||||
|
||||
|
||||
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
https://www.ibm.com/developerworks/cn/linux/l-cn-systemtap1/
|
||||
|
||||
|
||||
kprobe使用实例
|
||||
本文附带的包包含了三个示例模块,kprobe-exam.c是kprobes使用示例,jprobe-exam.c是jprobes使用示例,kretprobe-exam.c是kretprobes使用示例,读者可以下载该包并执行如下指令来实验这些模块:
|
||||
$ tar -jxvf kprobes-examples.tar.bz2
|
||||
$ cd kprobes-examples
|
||||
$ make
|
||||
…
|
||||
$ su -
|
||||
…
|
||||
$ insmod kprobe-example.ko
|
||||
$ dmesg
|
||||
…
|
||||
$ rmmod kprobe-example
|
||||
$ dmesg
|
||||
…
|
||||
$ insmod jprobe-example.ko
|
||||
$ cat kprobe-example.c
|
||||
$dmesg
|
||||
…
|
||||
$ rmmod jprobe-example
|
||||
$ dmesg
|
||||
…
|
||||
$ insmod kretprobe-example.ko
|
||||
$ dmesg
|
||||
…
|
||||
$ ls -Rla / > /dev/null &
|
||||
$ dmesg
|
||||
…
|
||||
$ rmmod kretprobe-example
|
||||
$ dmesg
|
||||
…
|
||||
$
|
||||
示例模块kprobe-exame.c探测schedule()函数,在探测点执行前后分别输出当前正在运行的进程、所在的CPU以及preempt_count(),当卸载该模块时将输出该模块运行时间以及发生的调度次数。这是该模块在作者系统上的输出:
|
||||
kprobe registered
|
||||
current task on CPU#1: swapper (before scheduling), preempt_count = 0
|
||||
current task on CPU#1: swapper (after scheduling), preempt_count = 0
|
||||
current task on CPU#0: insmod (before scheduling), preempt_count = 0
|
||||
current task on CPU#0: insmod (after scheduling), preempt_count = 0
|
||||
current task on CPU#1: klogd (before scheduling), preempt_count = 0
|
||||
current task on CPU#1: klogd (after scheduling), preempt_count = 0
|
||||
current task on CPU#1: klogd (before scheduling), preempt_count = 0
|
||||
current task on CPU#1: klogd (after scheduling), preempt_count = 0
|
||||
current task on CPU#1: klogd (before scheduling), preempt_count = 0
|
||||
…
|
||||
Scheduling times is 5918 during of 7655 milliseconds.
|
||||
kprobe unregistered
|
||||
示例模块jprobe-exam.c是一个jprobes探测例子,它示例了获取系统调用open的参数,但读者不要试图在实际的应用中这么使用,因为copy_from_user可能导致睡眠,而kprobe并不允许在探测点处理函数中这么做(请参看前面内容了解详细描述)。
|
||||
|
||||
这是该模块在作者系统上的输出:
|
||||
Registered a jprobe.
|
||||
process 'cat' call open('/etc/ld.so.cache', 0, 0)
|
||||
process 'cat' call open('/lib/libc.so.6', 0, -524289)
|
||||
process 'cat' call open('/usr/lib/locale/locale-archive', 32768, 1)
|
||||
process 'cat' call open('/usr/share/locale/locale.alias', 0, 438)
|
||||
process 'cat' call open('/usr/lib/locale/en_US.UTF-8/LC_CTYPE', 0, 0)
|
||||
process 'cat' call open('/usr/lib/locale/en_US.utf8/LC_CTYPE', 0, 0)
|
||||
process 'cat' call open('/usr/lib/gconv/gconv-modules.cache', 0, 0)
|
||||
process 'cat' call open('kprobe-exam.c', 32768, 0)
|
||||
…
|
||||
process 'rmmod' call open('/etc/ld.so.cache', 0, 0)
|
||||
process 'rmmod' call open('/lib/libc.so.6', 0, -524289)
|
||||
process 'rmmod' call open('/proc/modules', 0, 438)
|
||||
jprobe unregistered
|
||||
示例模块kretprobe-exam.c是一个返回探测例子,它探测系统调用open并输出返回值小于0的情况。它也有意设置maxactive为1,以便示例丢失探测运行的情况,当然,只有系统并发运行多个sys_open才可能导致这种情况,因此,读者需要有SMP的系统或者有超线程支持才能看到这种情况。如果读者比较仔细,会看到在前面的命令有”ls -Rla / > /dev/null & ,那是专门为了导致出现丢失探测运行的。
|
||||
|
||||
这是该模块在作者系统上的输出:
|
||||
Registered a return probe.
|
||||
sys_open returns -2
|
||||
sys_open returns -2
|
||||
sys_open returns -2
|
||||
sys_open returns -2
|
||||
sys_open returns -2
|
||||
sys_open returns -2
|
||||
sys_open returns -2
|
||||
sys_open returns -2
|
||||
sys_open returns -2
|
||||
sys_open returns -2
|
||||
sys_open returns -2
|
||||
sys_open returns -2
|
||||
…
|
||||
kretprobe unregistered
|
||||
Missed 11 sys_open probe instances.
|
||||
回页首
|
||||
小结
|
||||
本文详细地讲解了kprobe的方方面面并给出实际的例子代码帮助读者学习和使用kprobe。本文是系列文章“Linux下的一个全新的性能测量和调式诊断工具 -- Systemtap”之一,有兴趣的读者可以阅读该系列文章之二和三。
|
||||
@@ -0,0 +1,73 @@
|
||||
/* 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 == NULL)
|
||||
{
|
||||
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");
|
||||
@@ -0,0 +1,18 @@
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
|
||||
obj-m := kretprobe-exam.o
|
||||
|
||||
else
|
||||
|
||||
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
|
||||
PWD := $(shell pwd)
|
||||
|
||||
all:
|
||||
make -C $(KERNELDIR) M=$(PWD) modules
|
||||
|
||||
clean:
|
||||
make -C $(KERNELDIR) M=$(PWD) clean
|
||||
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,48 @@
|
||||
/*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->ax;
|
||||
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,0 +1 @@
|
||||
kernel//home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/driver/probe/test.ko
|
||||
@@ -0,0 +1,78 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kprobes.h>
|
||||
|
||||
/*
|
||||
* Jumper probe for do_fork.
|
||||
* Mirror principle enables access to arguments of the probed routine
|
||||
* from the probe handler.
|
||||
*/
|
||||
|
||||
/* Proxy routine having the same arguments as actual do_fork() routine */
|
||||
static long jdo_fork(unsigned long clone_flags, unsigned long stack_start,
|
||||
struct pt_regs *regs, unsigned long stack_size,
|
||||
int __user *parent_tidptr, int __user *child_tidptr)
|
||||
{
|
||||
printk(KERN_INFO "jprobe: clone_flags = 0x%lx, stack_size = 0x%lx,"
|
||||
" regs = 0x%p\n",
|
||||
clone_flags, stack_size, regs);
|
||||
|
||||
/* Always end with a call to jprobe_return(). */
|
||||
jprobe_return();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
asmlinkage __visible void __sched jschedule(void)
|
||||
{
|
||||
|
||||
/* Always end with a call to jprobe_return(). */
|
||||
jprobe_return();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct jprobe my_jprobe = {
|
||||
.entry = jschedule,
|
||||
/* 注意 symbol_name与addr不能同时存在
|
||||
* 参见kprobe_addr函数--http://lxr.free-electrons.com/source/kernel/kprobes.c#L1359
|
||||
* 否则会提示参数错误ERR_PTR(-EINVAL);
|
||||
* 内核中errno的值在http://lxr.free-electrons.com/source/include/uapi/asm-generic/errno-base.h#L25
|
||||
* */
|
||||
.kp = {
|
||||
.symbol_name = "schedule",
|
||||
//.addr
|
||||
},
|
||||
};
|
||||
|
||||
static int __init jprobe_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
//my_jprobe.kp.symbol_name = "_do_fork";
|
||||
//my_jprobe.kp.addr = kallsyms_lookup_name("_do_fork");
|
||||
|
||||
if(my_jprobe.kp.symbol_name == NULL)
|
||||
{
|
||||
my_jprobe.kp.addr = (kprobe_opcode_t *)kallsyms_lookup_name("_do_fork");
|
||||
printk("find _do_fork address at 0x%p\n", my_jprobe.kp.addr);
|
||||
}
|
||||
|
||||
ret = register_jprobe(&my_jprobe);
|
||||
if (ret < 0) {
|
||||
printk(KERN_INFO "register_jprobe failed, returned %d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
printk(KERN_INFO "Planted jprobe at %p, handler addr %p\n",
|
||||
my_jprobe.kp.addr, my_jprobe.entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit jprobe_exit(void)
|
||||
{
|
||||
unregister_jprobe(&my_jprobe);
|
||||
printk(KERN_INFO "jprobe at %p unregistered\n", my_jprobe.kp.addr);
|
||||
}
|
||||
|
||||
module_init(jprobe_init)
|
||||
module_exit(jprobe_exit)
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1,35 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/vermagic.h>
|
||||
#include <linux/compiler.h>
|
||||
|
||||
MODULE_INFO(vermagic, VERMAGIC_STRING);
|
||||
|
||||
__visible struct module __this_module
|
||||
__attribute__((section(".gnu.linkonce.this_module"))) = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.init = init_module,
|
||||
#ifdef CONFIG_MODULE_UNLOAD
|
||||
.exit = cleanup_module,
|
||||
#endif
|
||||
.arch = MODULE_ARCH_INIT,
|
||||
};
|
||||
|
||||
static const struct modversion_info ____versions[]
|
||||
__used
|
||||
__attribute__((section("__versions"))) = {
|
||||
{ 0xcd71858e, __VMLINUX_SYMBOL_STR(module_layout) },
|
||||
{ 0xe16b0d30, __VMLINUX_SYMBOL_STR(unregister_jprobe) },
|
||||
{ 0xb1bedeb7, __VMLINUX_SYMBOL_STR(register_jprobe) },
|
||||
{ 0x27e1a049, __VMLINUX_SYMBOL_STR(printk) },
|
||||
{ 0xe007de41, __VMLINUX_SYMBOL_STR(kallsyms_lookup_name) },
|
||||
{ 0x1b9aca3f, __VMLINUX_SYMBOL_STR(jprobe_return) },
|
||||
{ 0xbdfb6dbb, __VMLINUX_SYMBOL_STR(__fentry__) },
|
||||
};
|
||||
|
||||
static const char __module_depends[]
|
||||
__used
|
||||
__attribute__((section(".modinfo"))) =
|
||||
"depends=";
|
||||
|
||||
|
||||
MODULE_INFO(srcversion, "2312B77A1AEAF9D3AA41544");
|
||||
Reference in New Issue
Block a user