Rufnummer an Namen signalisieren?

Lesezeit: 7 Minuten

Wie kann ich den Signalnamen schnell von seiner Nummer erhalten? Es gibt strsignal()aber ich möchte nur den Namen, zB SIGUSR1

Mit anderen Worten, wenn wir Makros mögen
SIGUSR1 -> 12
haben wir sowas
12 -> SIGUSR1 ?

  • In meinem /usr/include/sys/signal.halle Signalnamen sind einfach #defined-Konstanten. Das heißt, der Präprozessor hat sie bis zur Ausführung des Compilers bereits durch konstante Integer ersetzt – den symbolischen Namen existiert nicht was das Programm betrifft. Was genau versuchst du hier zu tun?

    – Karl Norum

    12. Mai 2013 um 16:37 Uhr

  • @CarlNorum, nichts Besonderes, nur ausgefallene Ausgabe. Ich dachte, die tatsächlichen Namen könnten woanders gespeichert werden, damit ich sie bekommen könnte.

    – Mike Rolle

    12. Mai 2013 um 16:42 Uhr

  • Wenn Sie “ausgefallene Ausgabe” wollen, ist das nicht genau das Richtige strsignal ist für?

    – Karl Norum

    12. Mai 2013 um 16:43 Uhr

  • Ja, es ist schick, aber nicht so, wie ich es will 🙂 Nur neugierig, überhaupt kein Problem.

    – Mike Rolle

    12. Mai 2013 um 16:46 Uhr

  • Mein strsignal Manpage sagt, dass Sie die Namen direkt von bekommen können sys_signame.

    – Karl Norum

    12. Mai 2013 um 16:48 Uhr

Benutzeravatar von Carl Norum
Karl Norum

Mein strsignal(3) Manpage sagt, dass Sie die Namen direkt von der erhalten können sys_signame Reihe. Hier ist ein einfaches Beispielprogramm, das ich geschrieben habe, um es zu testen:

#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;
}

Ich denke, dieses Programm erzeugt die Ausgabe, die Sie suchen:

$ ./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

  • Nur strsignal scheint von POSIX definiert zu sein, wie es scheint, Array-Deklarationen sys_signame scheint eine Erweiterung zu sein.

    – Jens Gustedt

    12. Mai 2013 um 20:53 Uhr

  • Dies ist also vielleicht eine Antwort auf das Problem, das das OP hat, wenn es OS X verwendet, aber keine Antwort auf die Frage, wie sie formuliert ist.

    – Jens Gustedt

    13. Mai 2013 um 6:24 Uhr

  • ⁺¹, aber beachten Sie, dass der Array-Name wahrscheinlich geändert wurde – es ist sys_siglist.

    – Hallo Engel

    16. Oktober 2018 um 14:10 Uhr

Benutzeravatar von Socowi
Socowi

glib 2.32 (veröffentlicht am 05.08.2020) hat die Funktion eingeführt sigabbrev_np(int). Seit dieser Version können Sie nicht verwenden sys_siglist[] auch nicht mehr.

Aus man strsignal:

Das sigabbrev_np() Die Funktion gibt den abgekürzten Namen des Signals zurück, sig. Zum Beispiel den Wert gegeben SIGINTes gibt die Zeichenfolge zurück "INT".
[…]

sigdescr_np() und sigdabbrev_np() tauchten erstmals in glibc 2.32 auf. Ab Version 2.32 wird das sys_siglist-Symbol nicht mehr von glibc exportiert.

Und von der Versionshinweise:

Die Funktionen sigabbrev_np und sigdescr_np wurde hinzugefügt. Das sigabbrev_np gibt den abgekürzten Signalnamen zurück (zB "HUP" zum SIGHUP) […] beide Funktionen geben NULL für eine ungültige Signalnummer zurück.

Sie sollten stattdessen verwendet werden sys_siglist oder sys_sigabbrev und sie sind sowohl thread- als auch asynchronsignalsicher. Diese Funktionen sind GNU-Erweiterungen.

Getestet unter Code auf Ubuntu 16.04 und MIPS und es funktioniert gut.

#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;
}

Die Ausgabe des obigen Codes auf 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

Die Ausgabe des obigen Codes auf 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

  • aber es gibt kein SIGHANGUP oder SIGINTERRUPT, sie sind SIGHUP und SIGINT. Die mit Leerzeichen sind noch offensichtlicher falsch. Das einzige, was hier richtig ist, ist SIGQUIT …

    – Ilkkachu

    13. Oktober 2021 um 17:41 Uhr

Benutzeravatar von pilcrow
Pilkrähe

Wie Jens Gustedt vor Jahren in Kommentaren betonte, sys_signname und sys_siglist sind nicht tragbar.

Da diese Frage markiert ist [unix]können Sie am portabelsten #ifdef Ihren Weg zu einer für Ihre Umgebung spezifischen Zuordnung von Namen und numerischen Werten. Etwas wie:

//
//  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;
}

Dazu braucht es einige a priori Kenntnis Ihrer Plattform natürlich.

Möglicherweise können Sie ein globales Array wie folgt deklarieren

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};

und kann es verwenden, um den Signalnamen im Signal-Handler zu drucken, wie z

void sig_handler(int signum){
     printf("Received signal : %s\n", signame[signum]);
}

  • Dies ist eine schlechte Idee, da die meisten Signalnummern von der Implementierung abhängig sind. SIGKILL ist immer 9, aber nicht alle Signale haben solche festen Nummern.

    – Dietrich Ep

    3. November 2016 um 20:21 Uhr

  • aber es ist schön, es in einem Signalhandler verwenden zu müssen, da strsignal nicht signalsicher ist

    – SRombauten

    4. Januar 2018 um 10:24 Uhr

  • Dies ist eine schlechte Idee, da die meisten Signalnummern von der Implementierung abhängig sind. SIGKILL ist immer 9, aber nicht alle Signale haben solche festen Nummern.

    – Dietrich Ep

    3. November 2016 um 20:21 Uhr

  • aber es ist schön, es in einem Signalhandler verwenden zu müssen, da strsignal nicht signalsicher ist

    – SRombauten

    4. Januar 2018 um 10:24 Uhr

1394710cookie-checkRufnummer an Namen signalisieren?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy