java 中关于自定义信号在linux下的实现

在java 中调用Signal的方法handle可以去注册一个信号的处理函数,方法的如下:


比如常用的addShutdownHook钩子函数里,就是在Terminator.setup();的时候将Shutdown.exit 的函数注册到了信号 SHUTDOWN1_SIGNAL(SIGHUP), SHUTDOWN2_SIGNAL(SIGINT), SHUTDOWN3_SIGNAL(SIGTERM)中,当线程接受到信号时,通过调用函数Shutdown.exit的调用hook中的钩子函数。

在笔者的文章(java 中关于信号的处理在linux下的实现)也提到jdk如何处理信号的,那么调用handle里是不是直接就把这个方法注册进了信号处理呢?

请注意,handle是一个java的方法,而注册信号函数是c的代码,显然不能简单的将java的方法直接提供给c调用,其次信号处理函数是在内核态中处理,安全性和执行时间的长短将影响到内核的信号调度。

先看java源码,如下面所示

在native code hand0里并没有将handle的方法传进去,只是传了一个整型值。

在c++代码中hand0里调用了函数JVM_RegisterSignal,具体来看一下这个函数的实现


因为传进的值是2,那么真正在c++里的信号处理函数实际上os::user_handler(),同时jvm也保护了几个信号,不允许外部改变信号的处理函数。

一切豁然开朗,笔者的博客(java 中关于信号的处理在linux下的实现)已经提到过这个函数,通过os:signal_notify 去通知signal dispatcher 线程的os::signal_wait,也就是接受到信号的线程通过信号函数notify到处理信号的线程(signal dispatcher ),最后由该线程做后续的事情。

具体来看signal dispatcher 的thread entry


也就是在jvm的c++源码中,反调用了java的方法,也就是signal.java中的dispatch(int number),方法dispatch中才是真正的调用了在文章开头提到的注册到Signal的方法handle。

dispatch方法中仍然起了一个新的线程去处理handle,这样就不会blocksignal dispatcher 线程。

你可能感兴趣的:(linux)