linux下信号跟踪:jprobe_signal

问题描述:在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*

 

你可能感兴趣的:(代码)