killコマンドのテーブルはどこから来るのか

kill -lコマンドで、シグナルの一覧を表示することができます。

takk@deb8:~$ kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX    
takk@deb8:~$ 

どうやって表示しているのでしょうか。
例によってソースを落としてきます。

takk@deb8:~$ apt-get source coreutils
takk@deb8:~$ cd coreutils-8.23/src
takk@deb8:~/coreutils-8.23/src$ 

killコマンドのソース内をgrepします。1番のSIGHUPを検索します。

takk@deb8:~/coreutils-8.23/src$ grep SIGHUP kill.c
takk@deb8:~/coreutils-8.23/src$ 

どういうことでしょう。見つかりません。
では、もう少し見つかりやすいキーワードとして、SIGで検索します。

takk@deb8:~/coreutils-8.23/src$ grep SIG kill.c
#if ! (HAVE_DECL_STRSIGNAL || defined strsignal)
# if ! (HAVE_DECL_SYS_SIGLIST || defined sys_siglist)
#  if HAVE_DECL__SYS_SIGLIST || defined _sys_siglist
#  elif HAVE_DECL___SYS_SIGLIST || defined __sys_siglist
# if HAVE_DECL_SYS_SIGLIST || defined sys_siglist
#  define strsignal(signum) (0 <= (signum) && (signum) <= SIGNUM_BOUND \
Usage: %s [-s SIGNAL | -SIGNAL] PID...\n\
  or:  %s -l [SIGNAL]...\n\
  or:  %s -t [SIGNAL]...\n\
  -s, --signal=SIGNAL, -SIGNAL\n\
SIGNAL may be a signal name like 'HUP', or a signal number like '1',\n\
   number width, and SIGNUM is the signal number to print.  The
   maximum name width is NAME_WIDTH, and SIGNAME is the name to print.  */
  char signame[SIG2STR_MAX];
      for (signum = 1; signum <= SIGNUM_BOUND / 10; signum *= 10)
      for (signum = 1; signum <= SIGNUM_BOUND; signum++)
        for (signum = 1; signum <= SIGNUM_BOUND; signum++)
        for (signum = 1; signum <= SIGNUM_BOUND; signum++)
/* Send signal SIGNUM to all the processes or process groups specified
  char signame[SIG2STR_MAX];
    signum = SIGTERM;
takk@deb8:~/coreutils-8.23/src$ 

途中for文がありますね。ということは、killコマンドの-lオプションで表示する内容は、for文で回して表示しているということも考えられるでしょう。
上にでてくるfor文の後方も表示してみます。

takk@deb8:~/coreutils-8.23/src$ grep 'for.*signum' -A3 kill.c
      for (signum = 1; signum <= SIGNUM_BOUND / 10; signum *= 10)
        num_width++;

      /* Compute the maximum width of a signal name.  */
      for (signum = 1; signum <= SIGNUM_BOUND; signum++)
        if (sig2str (signum, signame) == 0)
          {
            size_t len = strlen (signame);
--
        for (signum = 1; signum <= SIGNUM_BOUND; signum++)
          if (sig2str (signum, signame) == 0)
            print_table_row (num_width, signum, name_width, signame);
    }
--
        for (signum = 1; signum <= SIGNUM_BOUND; signum++)
          if (sig2str (signum, signame) == 0)
            puts (signame);
    }
takk@deb8:~/coreutils-8.23/src$ 

ありました。print_table_row関数。次はこの関数をgrepします。

takk@deb8:~/coreutils-8.23/src$ grep '^print_table_row' -A10 kill.c
print_table_row (unsigned int num_width, int signum,
                 unsigned int name_width, char const *signame)
{
  char const *description = strsignal (signum);
  printf ("%*d %-*s %s\n", num_width, signum, name_width, signame,
          description ? description : "?");
}

/* Print a list of signal names.  If TABLE, print a table.
   Print the names specified by ARGV if nonzero; otherwise,
   print all known names.  Return a suitable exit status.  */
takk@deb8:~/coreutils-8.23/src$ 

strsignalという関数でシグナルの名前を取得しているようです。
以下、man strsignalの抜粋です。

説明
       strsignal()  関数は、引数 sig で渡されたシグナル番号を 説明する文字列を
       返す。 文字列は、次の strsignal()  が呼ばれるまでの間だけ使用できる。

       配列 sys_siglist はシグナルを説明する文字列を保持しており、  配列へのア
       クセスにはシグナル番号を添え字として用いる事ができる。 出来るだけこの配
       列の代わりに strsignal()  関数を 使うべきである。

返り値
       strsignal()  関数は、シグナルの適切な説明を返す。  もしシグナル番号が不
       正な場合は、未知のシグナル  (unknown  signal) を示す メッセージを返す。
       (Linux はそうではないが)不正なシグナル番号に対して、 NULL  を返すシステ
       ムもある。

なるほど、すっきりしました。

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA