问题描述:在linux环境下,有时候进程会异常退出,这个时候可以用strace跟踪进程的运行情况。如果是进程内部错误,则strace日志可以看到进程的异常错误点。但如果是被其它人或进程杀掉(kill),则strace日志里只能看到被杀信息:"+++ killed by SIGKILL +++"。此时要找到“杀手”进程,就需要跟踪信号量,找出是谁发送了信号量给目标进程。
/*jprobe_signal.c,基于jprobe,注册钩子函数,在信号发送的地方,根据需要,打印发送信号的进程,发送的信号量,信号接收的目标进程。
*/
#include#include #include #include static int g_pid=0; //-1=all process static int g_sig=9; //SIGKILL, 0=all signal module_param_named(pid,g_pid,int,S_IRUGO|S_IWUSR); module_param_named(signal,g_sig,int,S_IRUGO|S_IWUSR); MODULE_PARM_DESC(pid, "The specified process PID,-1 Reprensent all processes. 0 Represent no processes be traced. default is 0"); MODULE_PARM_DESC(signal, "The signal that needs to be tracked,0 represent all signal. default is 9"); static int jsend_signal(int sig,struct siginfo *info,struct task_struct *t,int group) { struct task_struct *parent=NULL; int prev_pid=0; if(((g_pid < 0) ||(t->pid==g_pid))&&((g_sig==0)||(sig==g_sig))){ printk(KERN_INFO "jprobe_signal:PID %d name:%s send SIG %d to PID=%d,name=%s\n",current->pid,current->comm,sig,t->pid,t->comm); parent=current->parent; prev_pid=current->pid; while(parent&&(parent->pid >= 1)){ printk(KERN_INFO"jprobe_signal:PID %d create by Parent Pid:%d,name:%s\n",prev_pid,parent->pid,parent->comm); prev_pid=parent->pid; parent=parent->parent; } } /* Always end with a call to jprobe_return(). */ jprobe_return(); return 0; } static struct jprobe my_jprobe = { .entry = jsend_signal, .kp = { .symbol_name = "send_signal", }, }; static int __init jprobe_init(void) { int ret; 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("Dual BSD/GPL");
Makefile 文件:
ifneq ($(KERNELRELEASE),) obj-m := jprobe_signal.o else KERNELDIR =/usr/src/$(shell uname -r)/ PWD := $(shell pwd) default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules endif .PHONY: clean clean: -rm -rf *.mod.c *.o *.order *.sym .j* .tmp*