加入收藏 | 设为首页 | 会员中心 | 我要投稿 开发网_开封站长网 (http://www.0378zz.com/)- 科技、AI行业应用、媒体智能、低代码、办公协同!
当前位置: 首页 > 教程 > 正文

Java 中关于自定义信号在Linux下的达成

发布时间:2021-11-22 10:31:41 所属栏目:教程 来源:互联网
导读:在Java 中调用Signal的方法handle可以去注册一个信号的处理函数,方法的如下: public static synchronized SignalHandler handle(Signal sig, SignalHandler handler) { .... } 比如常用的addShutdownHook钩子函数里,就是在 Terminator.setup();的时候将Shut
在Java 中调用Signal的方法handle可以去注册一个信号的处理函数,方法的如下:
 
public static synchronized SignalHandler handle(Signal sig,
                            SignalHandler handler) {
....
}
 
比如常用的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源码,如下面所示
 
public static synchronized SignalHandler handle(Signal sig,
                        SignalHandler handler)
throws IllegalArgumentException {
long newH = (handler instanceof NativeSignalHandler) ?
              ((NativeSignalHandler)handler).getHandler() : 2;
long oldH = handle0(sig.number, newH);
if (oldH == -1) {
    throw new IllegalArgumentException
    ("Signal already used by VM: " + sig);
}
signals.put(new Integer(sig.number), sig);
synchronized (handlers) {
    SignalHandler oldHandler = (SignalHandler)handlers.get(sig);
    handlers.remove(sig);
    if (newH == 2) {
        handlers.put(sig, handler);         
    }
    if (oldH == 0) {
        return SignalHandler.SIG_DFL;
    } else if (oldH == 1) {
        return SignalHandler.SIG_IGN;
    } else if (oldH == 2) {
        return oldHandler;
    } else {
        return new NativeSignalHandler(oldH);
    }
}
  }
 
在native code hand0里并没有将handle的方法传进去,只是传了一个整型值。
 
在c++代码中hand0里调用了函数 JVM_RegisterSignal,具体来看一下这个函数的实现
 
JVM_ENTRY_NO_ENV(void*, JVM_RegisterSignal(jint sig, void* handler))
  // Copied from classic vm
  // signals_md.c      1.4 98/08/23
  void* newHandler = handler == (void *)2
                  ? os::user_handler()
                  : handler;
  switch (sig) {
    /* The following are already used by the VM. */
    case INTERRUPT_SIGNAL:
    case SIGFPE:
    case SIGILL:
    case SIGSEGV:
 
    /* The following signal is used by the VM to dump thread stacks unless
      ReduceSignalUsage is set, in which case the user is allowed to set
      his own _native_ handler for this signal; thus, in either case,
      we do not allow JVM_RegisterSignal to change the handler. */
    case BREAK_SIGNAL:
      return (void *)-1;
 
    /* The following signals are used for Shutdown Hooks support. However, if
      ReduceSignalUsage (-Xrs) is set, Shutdown Hooks must be invoked via
      System.exit(), Java is not allowed to use these signals, and the the
      user is allowed to set his own _native_ handler for these signals and
      invoke System.exit() as needed. Terminator.setup() is avoiding
      registration of these signals when -Xrs is present.
      - If the HUP signal is ignored (from the nohup) command, then Java
        is not allowed to use this signal.
    */
 
    case SHUTDOWN1_SIGNAL:
    case SHUTDOWN2_SIGNAL:
    case SHUTDOWN3_SIGNAL:
      if (ReduceSignalUsage) return (void*)-1;
      if (os::Linux::is_sig_ignored(sig)) return (void*)1;
  }
 
  void* oldHandler = os::signal(sig, newHandler);
  if (oldHandler == os::user_handler()) {
      return (void *)2;
  } else {
      return oldHandler;
  }
JVM_END
 
void* newHandler = handler == (void *)2
                  ? os::user_handler()
                  : handler;
 
 

(编辑:开发网_开封站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读