【问题标题】:C - Get Process ID of signalling processC - 获取信令进程的进程 ID
【发布时间】:2013-02-28 08:19:51
【问题描述】:

所以这是我现在遇到的问题,我创建了 2 个不同的程序(1 个将管理另一个,而另一个将被执行多次)。这些程序将通过信号来回通信。我的问题是,是否有可能(以及如何)获取发送信号的程序的进程 ID。 我的程序使用 signal() 捕获信号并使用 kill() 发送它们。

【问题讨论】:

    标签: c signals pid


    【解决方案1】:

    要获取发送信号的进程的进程 ID,您需要将其包含在选项 SA_SIGINFO 中。如果你这样做,sigaction 的接口会略有不同。以下是要使用的正确处理程序以及如何设置它的示例。 (我将 SA_RESTART 作为一个选项包括在内只是因为它通常是一个好主意,但不是必需的)

    // example of a handler which checks the signalling pid
    void handler(int sig, siginfo_t* info, void* vp) { 
      if (info->si_pid != getpid()) {
        // not from me (or my call to alarm)
        return;
      }
      // from me.  let me know alarm when off
      alarmWentOff = 1;
    } 
    

    这是我设置处理程序的一般代码:

    typedef void InfoHandler(int, siginfo_t *, void *);
    
    InfoHandler*
    SignalWithInfo(int signum, InfoHandler* handler)
    {
      struct sigaction action, old_action;
    
      memset(&action, 0, sizeof(struct sigaction));
      action.sa_sigaction = handler;  
      sigemptyset(&action.sa_mask); /* block sigs of type being handled */
      action.sa_flags = SA_RESTART|SA_SIGINFO; /* restart syscalls if possible */
    
      if (sigaction(signum, &action, &old_action) < 0)
    perror("Signal error");
      return (old_action.sa_sigaction);
    }
    

    最后,对于这种特殊情况:

    SignalWithInfo(SIGALRM, handler);  
    

    【讨论】:

      【解决方案2】:

      虽然 signal() 在标准 C 库中,但此函数不可移植,其行为取决于系统。最好使用 POSIX.1 的 sigaction()。

      这是一个如何将 sigaction 与处理程序 void h(int sig) 一起使用的示例:

      int mysignal (int sig, void (*h)(int), int options)
      {
          int r;
          struct sigaction s;
          s.sa_handler = h;
          sigemptyset (&s.sa_mask);
          s.sa_flags = options;
          r = sigaction (sig, &s, NULL);
          if (r < 0) perror (__func__);
          return r;
      }
      

      选项在 man sigaction 中描述。一个不错的选择是options=SA_RESTART

      要知道发送信号的进程的PID,设置options=SA_SIGINFO,并使用sa_sigaction回调而不是sa_handler;它将收到一个siginfo_t 结构,具有一个si_pid 字段。您可以使用sigqueue 将数据与信号相关联。

      一般来说,使用信号以安全的方式进行通信是一个坏主意(当发送 n 个信号时,只有第一个有机会被传递;没有挂钩来关联其他数据;可用的用户信号是只有两个)。最好使用管道、命名管道或套接字。

      【讨论】:

        【解决方案3】:

        现在变了。信号信息显示的不是 1 个 pid,而是简单的数字。这符合killall过程。可能,有可能枚举 /proc/ 目录,当你找到 /proc/DIGIT 时,打开 /proc/DIGIT/comm,读取并关闭它。可能,acueried name 将是“shutdown”或“rebo​​ot”

        【讨论】:

          【解决方案4】:

          不要使用signal(),它已经过时了。如果有,请改用sigaction(),它提供了一个接口来获取发送者的进程ID。

          【讨论】:

          • 它不会捕获 sigkill 和 sigstop。例如,如果您在第二个进程中按 ctrl+c,则不会被 sigaction() 捕获。
          • 是的,很好,我如何用 sigaction() 捕捉它?
          • @Chris:对于sigaction() 示例以及关于信号处理的一些更新,请查看我前段时间写的this article
          猜你喜欢
          • 2017-05-23
          • 2018-02-25
          • 2011-03-31
          • 1970-01-01
          • 2016-01-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多