mirror of
https://github.com/gatieme/LDD-LinuxDeviceDrivers.git
synced 2026-09-24 22:43:42 +08:00
kernel debug tools...
This commit is contained in:
@@ -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,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 := data_breakpoint
|
||||
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
|
||||
#CFG_FLAGS += -O2 -I./
|
||||
#EXTRA_CFLAGS += $(C_FLAGS) $(CFG_INC) $(CFG_INC)
|
||||
|
||||
|
||||
|
||||
obj-m := $(MODULE_NAME).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,92 @@
|
||||
/*
|
||||
* data_breakpoint.c - Sample HW Breakpoint file to watch kernel data address
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* usage: insmod data_breakpoint.ko ksym=<ksym_name>
|
||||
*
|
||||
* This file is a kernel module that places a breakpoint over ksym_name kernel
|
||||
* variable using Hardware Breakpoint register. The corresponding handler which
|
||||
* prints a backtrace is invoked every time a write operation is performed on
|
||||
* that variable.
|
||||
*
|
||||
* Copyright (C) IBM Corporation, 2009
|
||||
*
|
||||
* Author: K.Prasad <prasad@linux.vnet.ibm.com>
|
||||
*/
|
||||
|
||||
// http://lxr.free-electrons.com/source/samples/hw_breakpoint/data_breakpoint.c
|
||||
#include <linux/module.h> /* Needed by all modules */
|
||||
#include <linux/kernel.h> /* Needed for KERN_INFO */
|
||||
#include <linux/init.h> /* Needed for the macros */
|
||||
#include <linux/kallsyms.h>
|
||||
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/hw_breakpoint.h>
|
||||
|
||||
struct perf_event * __percpu *sample_hbp;
|
||||
|
||||
static char ksym_name[KSYM_NAME_LEN] = "pid_max";
|
||||
module_param_string(ksym, ksym_name, KSYM_NAME_LEN, S_IRUGO);
|
||||
MODULE_PARM_DESC(ksym, "Kernel symbol to monitor; this module will report any"
|
||||
" write operations on the kernel symbol");
|
||||
|
||||
static void sample_hbp_handler(struct perf_event *bp,
|
||||
struct perf_sample_data *data,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
printk(KERN_INFO "%s value is changed\n", ksym_name);
|
||||
dump_stack();
|
||||
printk(KERN_INFO "Dump stack from sample_hbp_handler\n");
|
||||
}
|
||||
|
||||
static int __init hw_break_module_init(void)
|
||||
{
|
||||
int ret;
|
||||
struct perf_event_attr attr;
|
||||
|
||||
hw_breakpoint_init(&attr);
|
||||
attr.bp_addr = kallsyms_lookup_name(ksym_name);
|
||||
attr.bp_len = HW_BREAKPOINT_LEN_4;
|
||||
attr.bp_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R;
|
||||
|
||||
sample_hbp = register_wide_hw_breakpoint(&attr, sample_hbp_handler, NULL);
|
||||
if (IS_ERR((void __force *)sample_hbp)) {
|
||||
ret = PTR_ERR((void __force *)sample_hbp);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "HW Breakpoint for %s write installed\n", ksym_name);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
printk(KERN_INFO "Breakpoint registration failed\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit hw_break_module_exit(void)
|
||||
{
|
||||
unregister_wide_hw_breakpoint(sample_hbp);
|
||||
printk(KERN_INFO "HW Breakpoint for %s write uninstalled\n", ksym_name);
|
||||
}
|
||||
|
||||
module_init(hw_break_module_init);
|
||||
module_exit(hw_break_module_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("K.Prasad");
|
||||
MODULE_DESCRIPTION("ksym breakpoint");
|
||||
@@ -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,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,115 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kprobes.h>
|
||||
|
||||
|
||||
int handler_pre(struct kprobe *p, struct pt_regs *regs)
|
||||
{
|
||||
printk("current task on CPU#%d: %s (before), preempt_count = %d\n",
|
||||
smp_processor_id( ), current->comm, preempt_count( ));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void handler_post(struct kprobe *p, struct pt_regs *regs, unsigned long flags)
|
||||
{
|
||||
printk("current task on CPU#%d: %s (after), 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* 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 = jdo_fork,
|
||||
/* 注意 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 = "_do_fork",
|
||||
//.addr
|
||||
.pre_handler = handler_pre,
|
||||
.post_handler = handler_post,
|
||||
.fault_handler = handler_fault,
|
||||
},
|
||||
};
|
||||
|
||||
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 0
|
||||
my_jprobe.kp.pre_handler = handler_pre;
|
||||
my_jprobe.kp.post_handler = handler_post;
|
||||
my_jprobe.kp.fault_handler = handler_fault;
|
||||
#endif
|
||||
|
||||
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,100 @@
|
||||
/*
|
||||
* NOTE: This example is works on x86 and powerpc.
|
||||
* Here's a sample kernel module showing the use of kprobes to dump a
|
||||
* stack trace and selected registers when do_fork() is called.
|
||||
*
|
||||
* For more information on theory of operation of kprobes, see
|
||||
* Documentation/kprobes.txt
|
||||
*
|
||||
* You will see the trace data in /var/log/messages and on the console
|
||||
* whenever do_fork() is invoked to create a new process.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kprobes.h>
|
||||
|
||||
/* For each probe you need to allocate a kprobe structure */
|
||||
static struct kprobe kp = {
|
||||
.symbol_name = "do_fork",
|
||||
};
|
||||
|
||||
/* kprobe pre_handler: called just before the probed instruction is executed */
|
||||
static int handler_pre(struct kprobe *p, struct pt_regs *regs)
|
||||
{
|
||||
#ifdef CONFIG_X86
|
||||
printk(KERN_INFO "pre_handler: p->addr = 0x%p, ip = %lx,"
|
||||
" flags = 0x%lx\n",
|
||||
p->addr, regs->ip, regs->flags);
|
||||
#endif
|
||||
#ifdef CONFIG_PPC
|
||||
printk(KERN_INFO "pre_handler: p->addr = 0x%p, nip = 0x%lx,"
|
||||
" msr = 0x%lx\n",
|
||||
p->addr, regs->nip, regs->msr);
|
||||
#endif
|
||||
#ifdef CONFIG_MIPS
|
||||
printk(KERN_INFO "pre_handler: p->addr = 0x%p, epc = 0x%lx,"
|
||||
" status = 0x%lx\n",
|
||||
p->addr, regs->cp0_epc, regs->cp0_status);
|
||||
#endif
|
||||
|
||||
/* A dump_stack() here will give a stack backtrace */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* kprobe post_handler: called after the probed instruction is executed */
|
||||
static void handler_post(struct kprobe *p, struct pt_regs *regs,
|
||||
unsigned long flags)
|
||||
{
|
||||
#ifdef CONFIG_X86
|
||||
printk(KERN_INFO "post_handler: p->addr = 0x%p, flags = 0x%lx\n",
|
||||
p->addr, regs->flags);
|
||||
#endif
|
||||
#ifdef CONFIG_PPC
|
||||
printk(KERN_INFO "post_handler: p->addr = 0x%p, msr = 0x%lx\n",
|
||||
p->addr, regs->msr);
|
||||
#endif
|
||||
#ifdef CONFIG_MIPS
|
||||
printk(KERN_INFO "post_handler: p->addr = 0x%p, status = 0x%lx\n",
|
||||
p->addr, regs->cp0_status);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* fault_handler: this is called if an exception is generated for any
|
||||
* instruction within the pre- or post-handler, or when Kprobes
|
||||
* single-steps the probed instruction.
|
||||
*/
|
||||
static int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr)
|
||||
{
|
||||
printk(KERN_INFO "fault_handler: p->addr = 0x%p, trap #%dn",
|
||||
p->addr, trapnr);
|
||||
/* Return 0 because we don't handle the fault. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init kprobe_init(void)
|
||||
{
|
||||
int ret;
|
||||
kp.pre_handler = handler_pre;
|
||||
kp.post_handler = handler_post;
|
||||
kp.fault_handler = handler_fault;
|
||||
|
||||
ret = register_kprobe(&kp);
|
||||
if (ret < 0) {
|
||||
printk(KERN_INFO "register_kprobe failed, returned %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
printk(KERN_INFO "Planted kprobe at %p\n", kp.addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit kprobe_exit(void)
|
||||
{
|
||||
unregister_kprobe(&kp);
|
||||
printk(KERN_INFO "kprobe at %p unregistered\n", kp.addr);
|
||||
}
|
||||
|
||||
module_init(kprobe_init)
|
||||
module_exit(kprobe_exit)
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1,76 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
# 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 := ftrace_demo
|
||||
MODCFLAGS:=-O6 -Wall -DMODULE -D__KERNEL__ -DLINUX -std=c99
|
||||
|
||||
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,24 @@
|
||||
/*
|
||||
* ftrace_demo.c
|
||||
* http://www.ibm.com/developerworks/cn/linux/l-cn-ftrace3/
|
||||
* http://lxr.free-electrons.com/source/include/trace/events/context_tracking.h 貌似没实现
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int ftrace_demo_init(void)
|
||||
{
|
||||
trace_printk("Can not see this in trace unless loaded for the second time\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ftrace_demo_exit(void)
|
||||
{
|
||||
trace_printk("Module unloading\n");
|
||||
}
|
||||
|
||||
module_init(ftrace_demo_init);
|
||||
module_exit(ftrace_demo_exit);
|
||||
@@ -0,0 +1,81 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# 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 := trace-events-sample
|
||||
#MODCFLAGS:=-O2 -Wall -DMODULE -D__KERNEL__ -DLINUX -std=c99
|
||||
SRC := /home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/debug/trace/trace-events-sample
|
||||
EXTRA_CFLAGS += -I$(SRC)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
|
||||
|
||||
|
||||
|
||||
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 :
|
||||
cat /sys/kernel/debug/mydebug/a
|
||||
cat /sys/kernel/debug/mydebug/b
|
||||
cat /sys/kernel/debug/mydebug/subdir/c
|
||||
|
||||
clean:
|
||||
make -C $(KERNELDIR) M=$(PWD) clean
|
||||
rm -f modules.order Module.symvers Module.markers
|
||||
|
||||
.PHNOY:
|
||||
modules modules_install clean
|
||||
|
||||
|
||||
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
http://blog.csdn.net/arethe/article/details/6293505]
|
||||
http://lxr.free-electrons.com/source/Documentation/trace/tracepoints.txt
|
||||
https://lwn.net/Articles/410200/
|
||||
|
||||
|
||||
#1 驱动安装
|
||||
-------
|
||||
|
||||
|
||||
sudo insmod trace-events-sample.ko
|
||||
|
||||
|
||||
#2 检查驱动
|
||||
-------
|
||||
|
||||
cat /sys/kernel/debug/tracing/available_events | grep sample-trace
|
||||
|
||||
cd /sys/kernel/debug/tracing/events/sample-trace
|
||||
|
||||
|
||||
#3 列出所有的events
|
||||
-------
|
||||
|
||||
find /sys/kernel/debug/tracing/events -type d
|
||||
|
||||
cat /sys/kernel/debug/tracing/available_events
|
||||
|
||||
trace-cmd list
|
||||
|
||||
perf list 2>&1 | grep Tracepoint
|
||||
|
||||
#3 trace-cmd
|
||||
-------
|
||||
|
||||
sudo trace-cmd reset
|
||||
|
||||
sudo trace-cmd record -e sample-trace:foo_with_template_print
|
||||
|
||||
sudo trace-cmd report
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kthread.h>
|
||||
|
||||
/*
|
||||
* Any file that uses trace points, must include the header.
|
||||
* But only one file, must include the header by defining
|
||||
* CREATE_TRACE_POINTS first. This will make the C code that
|
||||
* creates the handles for the trace points.
|
||||
*/
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "trace-events-sample.h"
|
||||
|
||||
static const char *random_strings[] = {
|
||||
"Mother Goose",
|
||||
"Snoopy",
|
||||
"Gandalf",
|
||||
"Frodo",
|
||||
"One ring to rule them all"
|
||||
};
|
||||
|
||||
static void simple_thread_func(int cnt)
|
||||
{
|
||||
int array[6];
|
||||
int len = cnt % 5;
|
||||
int i;
|
||||
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(HZ);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
array[i] = i + 1;
|
||||
array[i] = 0;
|
||||
|
||||
/* Silly tracepoints */
|
||||
trace_foo_bar("hello", cnt, array, random_strings[len],
|
||||
tsk_cpus_allowed(current));
|
||||
|
||||
trace_foo_with_template_simple("HELLO", cnt);
|
||||
|
||||
trace_foo_bar_with_cond("Some times print", cnt);
|
||||
|
||||
trace_foo_with_template_cond("prints other times", cnt);
|
||||
|
||||
trace_foo_with_template_print("I have to be different", cnt);
|
||||
}
|
||||
|
||||
static int simple_thread(void *arg)
|
||||
{
|
||||
int cnt = 0;
|
||||
|
||||
while (!kthread_should_stop())
|
||||
simple_thread_func(cnt++);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct task_struct *simple_tsk;
|
||||
static struct task_struct *simple_tsk_fn;
|
||||
|
||||
static void simple_thread_func_fn(int cnt)
|
||||
{
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(HZ);
|
||||
|
||||
/* More silly tracepoints */
|
||||
trace_foo_bar_with_fn("Look at me", cnt);
|
||||
trace_foo_with_template_fn("Look at me too", cnt);
|
||||
}
|
||||
|
||||
static int simple_thread_fn(void *arg)
|
||||
{
|
||||
int cnt = 0;
|
||||
|
||||
while (!kthread_should_stop())
|
||||
simple_thread_func_fn(cnt++);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DEFINE_MUTEX(thread_mutex);
|
||||
|
||||
int foo_bar_reg(void)
|
||||
{
|
||||
pr_info("Starting thread for foo_bar_fn\n");
|
||||
/*
|
||||
* We shouldn't be able to start a trace when the module is
|
||||
* unloading (there's other locks to prevent that). But
|
||||
* for consistency sake, we still take the thread_mutex.
|
||||
*/
|
||||
mutex_lock(&thread_mutex);
|
||||
simple_tsk_fn = kthread_run(simple_thread_fn, NULL, "event-sample-fn");
|
||||
mutex_unlock(&thread_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void foo_bar_unreg(void)
|
||||
{
|
||||
pr_info("Killing thread for foo_bar_fn\n");
|
||||
/* protect against module unloading */
|
||||
mutex_lock(&thread_mutex);
|
||||
if (simple_tsk_fn)
|
||||
kthread_stop(simple_tsk_fn);
|
||||
simple_tsk_fn = NULL;
|
||||
mutex_unlock(&thread_mutex);
|
||||
}
|
||||
|
||||
static int __init trace_event_init(void)
|
||||
{
|
||||
simple_tsk = kthread_run(simple_thread, NULL, "event-sample");
|
||||
if (IS_ERR(simple_tsk))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit trace_event_exit(void)
|
||||
{
|
||||
kthread_stop(simple_tsk);
|
||||
mutex_lock(&thread_mutex);
|
||||
if (simple_tsk_fn)
|
||||
kthread_stop(simple_tsk_fn);
|
||||
simple_tsk_fn = NULL;
|
||||
mutex_unlock(&thread_mutex);
|
||||
}
|
||||
|
||||
module_init(trace_event_init);
|
||||
module_exit(trace_event_exit);
|
||||
|
||||
MODULE_AUTHOR("Steven Rostedt");
|
||||
MODULE_DESCRIPTION("trace-events-sample");
|
||||
MODULE_LICENSE("GPL");
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user