37

如何从其编号中快速获取信号名称?有strsignal(),但我只想要名字,例如 SIGUSR1

换句话说,如果我们有类似的宏,我们有类似 SIGUSR1 -> 12 的东西 12 -> SIGUSR1吗?

4

5 回答 5

22

我的strsignal(3)手册页说您可以直接从sys_signame数组中获取名称。这是我为测试它而编写的一个简单示例程序:

#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

void upcase(char *s)
{
    while (*s)
    {
        *s = toupper(*s);
        s++;        
    }
}

int main(void)
{    
    for (int sig = 1; sig < NSIG; sig++)
    {
        char *str = strdup(sys_signame[sig]);
        if (!str)
            return -1;

        upcase(str);
        printf("%2d -> SIG%s\n", sig, str);

        free(str);
    }

    return 0;
}

我认为该程序会产生您正在寻找的输出:

$ ./example 
 1 -> SIGHUP
 2 -> SIGINT
 3 -> SIGQUIT
 4 -> SIGILL
 5 -> SIGTRAP
 6 -> SIGABRT
 7 -> SIGEMT
 8 -> SIGFPE
 9 -> SIGKILL
10 -> SIGBUS
11 -> SIGSEGV
12 -> SIGSYS
13 -> SIGPIPE
14 -> SIGALRM
15 -> SIGTERM
16 -> SIGURG
17 -> SIGSTOP
18 -> SIGTSTP
19 -> SIGCONT
20 -> SIGCHLD
21 -> SIGTTIN
22 -> SIGTTOU
23 -> SIGIO
24 -> SIGXCPU
25 -> SIGXFSZ
26 -> SIGVTALRM
27 -> SIGPROF
28 -> SIGWINCH
29 -> SIGINFO
30 -> SIGUSR1
31 -> SIGUSR2
于 2013-05-12T16:56:20.287 回答
2

glib 2.32(2020-08-05 发布)引入了该功能sigabbrev_np(int)。从那个版本开始,你也不能再使用sys_siglist[]了。

来自man strsignal

sigabbrev_np()函数返回信号的缩写名称,sig。例如,给定 value SIGINT,它返回 string "INT"
[...]
sigdescr_np() 和 sigdabbrev_np() 首次出现在 glibc 2.32 中。从 2.32 版开始,glibc 不再导出 sys_siglist 符号。

发行说明

功能sigabbrev_npsigdescr_np已添加。sigabbrev_np返回缩写的信号名称(例如for "HUP"SIGHUP[...] 两个函数都为无效的信号编号返回 NULL。

应该使用它们而不是sys_siglistorsys_sigabbrev并且它们都是线程和异步信号安全的。这些函数是 GNU 扩展。

于 2021-07-22T08:36:05.607 回答
1

在 Ubuntu 16.04 和 MIPS 上测试了下面的代码,它工作正常。

#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

extern const char * const sys_siglist[];

void upcase(char *s)
{
    while (*s)
    {
        *s = toupper(*s);
        s++;
    }
}

int main(void)
{
    int sig;
    /*
       NSIG returns number of signals available in a system
       and it may vary according to platforms;Found on Ubuntu-16.04 it return 65
       where as in MIPS it is 31; Found in both the platforms it leads to core dump
       after signal 31 so limiting scanning of signal till 31 instead of using NSIG
    */
    for (sig = 1; sig < 32; sig++)
    {
        char *str = strdup(sys_siglist[sig]);
        if (!str)
            return -1;

        upcase(str);
        printf("%2d -> SIG%s\n", sig, str);

        free(str);
    }

    return 0;
}

以上代码在 Ubuntu-16.04(Intel x86_64 GNU/Linux)上的输出:

 1 -> SIGHANGUP
 2 -> SIGINTERRUPT
 3 -> SIGQUIT
 4 -> SIGILLEGAL INSTRUCTION
 5 -> SIGTRACE/BREAKPOINT TRAP
 6 -> SIGABORTED
 7 -> SIGBUS ERROR
 8 -> SIGFLOATING POINT EXCEPTION
 9 -> SIGKILLED
10 -> SIGUSER DEFINED SIGNAL 1
11 -> SIGSEGMENTATION FAULT
12 -> SIGUSER DEFINED SIGNAL 2
13 -> SIGBROKEN PIPE
14 -> SIGALARM CLOCK
15 -> SIGTERMINATED
16 -> SIGSTACK FAULT
17 -> SIGCHILD EXITED
18 -> SIGCONTINUED
19 -> SIGSTOPPED (SIGNAL)
20 -> SIGSTOPPED
21 -> SIGSTOPPED (TTY INPUT)
22 -> SIGSTOPPED (TTY OUTPUT)
23 -> SIGURGENT I/O CONDITION
24 -> SIGCPU TIME LIMIT EXCEEDED
25 -> SIGFILE SIZE LIMIT EXCEEDED
26 -> SIGVIRTUAL TIMER EXPIRED
27 -> SIGPROFILING TIMER EXPIRED
28 -> SIGWINDOW CHANGED
29 -> SIGI/O POSSIBLE
30 -> SIGPOWER FAILURE
31 -> SIGBAD SYSTEM CALL

上述代码在busybox(MIPS、Cavium)上的输出:

 1 -> SIGHANGUP
 2 -> SIGINTERRUPT
 3 -> SIGQUIT
 4 -> SIGILLEGAL INSTRUCTION
 5 -> SIGTRACE/BREAKPOINT TRAP
 6 -> SIGABORTED
 7 -> SIGEMT TRAP
 8 -> SIGFLOATING POINT EXCEPTION
 9 -> SIGKILLED
10 -> SIGBUS ERROR
11 -> SIGSEGMENTATION FAULT
12 -> SIGBAD SYSTEM CALL
13 -> SIGBROKEN PIPE
14 -> SIGALARM CLOCK
15 -> SIGTERMINATED
16 -> SIGUSER DEFINED SIGNAL 1
17 -> SIGUSER DEFINED SIGNAL 2
18 -> SIGCHILD EXITED
19 -> SIGPOWER FAILURE
20 -> SIGWINDOW CHANGED
21 -> SIGURGENT I/O CONDITION
22 -> SIGI/O POSSIBLE
23 -> SIGSTOPPED (SIGNAL)
24 -> SIGSTOPPED
25 -> SIGCONTINUED
26 -> SIGSTOPPED (TTY INPUT)
27 -> SIGSTOPPED (TTY OUTPUT)
28 -> SIGVIRTUAL TIMER EXPIRED
29 -> SIGPROFILING TIMER EXPIRED
30 -> SIGCPU TIME LIMIT EXCEEDED
31 -> SIGFILE SIZE LIMIT EXCEEDED
于 2019-04-04T08:31:57.953 回答
1

正如Jens Gustedt几年前在评论中指出的那样,sys_signamesys_siglist是不可移植的。

由于此问题已标记为[unix],因此您可以通过最便携#ifdef的方式来映射特定于您的环境的名称和数值。就像是:

//
//  const char * signame(int s)
//
//    return the name of the given signal number as a string,
//    or NULL if the number is unrecognized.
//
#define _POSIX_C_SOURCE 200809L
#include <signal.h>

#define SIGNAMEANDNUM(s)  { #s, s }

static struct {
  const char *name,
  int value,
} known_signals[] = {
  SIGNAMEANDNUM(SIGABRT),   // get the POSIX signals
  SIGNAMEANDNUM(SIGALRM),
  SIGNAMEANDNUM(SIGBUS),
  SIGNAMEANDNUM(SIGCHLD),
  /* ... */
  SIGNAMEANDNUM(SIGXFSZ),
#ifdef SIGUNUSUAL           // get nonstandard signals 
  SIGNAMEANDNUM(SIGUNUSUAL),
#endif
  /* ... */
};

const char *
signame(int s) {
  const char *name = NULL;

  for (int i = 0; i < sizeof(known_signals)/sizeof(*known_signals); i++) {
    if (s == known_signals[i].value) {
      name = known_signals[i].name;
      break;
    }
  }

  return name;
}

当然,这需要您对平台有一些先验知识。

于 2021-07-22T01:35:14.170 回答
-1

可能是,你可以声明一个全局数组,像这样

char *signame[]={"INVALID", "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGTRAP", "SIGABRT", "SIGBUS", "SIGFPE", "SIGKILL", "SIGUSR1", "SIGSEGV", "SIGUSR2", "SIGPIPE", "SIGALRM", "SIGTERM", "SIGSTKFLT", "SIGCHLD", "SIGCONT", "SIGSTOP", "SIGTSTP", "SIGTTIN", "SIGTTOU", "SIGURG", "SIGXCPU", "SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGWINCH", "SIGPOLL", "SIGPWR", "SIGSYS", NULL};

并可以使用它在信号处理程序中打印信号名称,例如

void sig_handler(int signum){
     printf("Received signal : %s\n", signame[signum]);
}
于 2016-02-03T01:12:51.057 回答