無料Wikiサービス | デモページ
検索

アクセス数
最近のコメント
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
はじめ - ノース
はじめ - ノース
はじめ - 楽打連動ユーザー
はじめ - 楽打連動ユーザー
Adsense
広告情報が設定されていません。

コアダンプファイル名


コアダンプファイル名は、 format_corename()の引数corenameに取得されます。*patternはファイル名を作成するパラメータで、/proc/sys/kernel/core_patternで、signrはコアダンプを発生させたシグナルです。
#define CORENAME_MAX_SIZE 64

void format_corename(char *corename, const char *pattern, long signr)
{
       const char *pat_ptr = pattern;
       char *out_ptr = corename;
       char *const out_end = corename + CORENAME_MAX_SIZE;
       int rc;
       int pid_in_pattern = 0;

       while (*pat_ptr) {
               if (*pat_ptr != '%') {
                       if (out_ptr == out_end)
                               goto out;
                       *out_ptr++ = *pat_ptr++;
               } else {
                       switch (*++pat_ptr) {
                       case 0:
                               goto out;
                       case '%':
                               if (out_ptr == out_end)
                                       goto out;
                               *out_ptr++ = '%';
                               break;
                       case 'p':
                               pid_in_pattern = 1;
                               rc = snprintf(out_ptr, out_end - out_ptr,
                                             "%d", current->tgid);
                               if (rc > out_end - out_ptr)
                                       goto out;
                               out_ptr += rc;
                               break;
                       case 'u':
                               rc = snprintf(out_ptr, out_end - out_ptr,
                                             "%d", current->uid);
                               if (rc > out_end - out_ptr)
                                       goto out;
                               out_ptr += rc;
                               break;
                       case 'g':
                               rc = snprintf(out_ptr, out_end - out_ptr,
                                             "%d", current->gid);
                               if (rc > out_end - out_ptr)
                                       goto out;
                               out_ptr += rc;
                               break;
                       case 's':
                               rc = snprintf(out_ptr, out_end - out_ptr,
                                             "%ld", signr);
                               if (rc > out_end - out_ptr)
                                       goto out;
                               out_ptr += rc;
                               break;
                        case 't': {
                               struct timeval tv;
                               do_gettimeofday(&tv);
                               rc = snprintf(out_ptr, out_end - out_ptr,
                                             "%lu", tv.tv_sec);
                               if (rc > out_end - out_ptr)
                                       goto out;
                               out_ptr += rc;
                               break;
                       }
                       case 'h':
                               down_read(&uts_sem);
                               rc = snprintf(out_ptr, out_end - out_ptr,
                                             "%s", system_utsname.nodename);
                               up_read(&uts_sem);
                               if (rc > out_end - out_ptr)
                                       goto out;
                               out_ptr += rc;
                               break;
                       case 'e':
                               rc = snprintf(out_ptr, out_end - out_ptr,
                                             "%s", current->comm);
                               if (rc > out_end - out_ptr)
                                       goto out;
                               out_ptr += rc;
                               break;
                       default:
                               break;
                       }
                       ++pat_ptr;
               }
       }
       if (!pid_in_pattern
           && (core_uses_pid || atomic_read(&current->mm->mm_users) != 1)) {
               rc = snprintf(out_ptr, out_end - out_ptr,
                             ".%d", current->tgid);
               if (rc > out_end - out_ptr)
                       goto out;
               out_ptr += rc;
       }
     out:
       *out_ptr = 0;
}
pat_ptr文字列に%がない時、pat_ptr文字列がそのままコアダンプファイル名になります。%の場合以下の内容に置き換わります。また、%の任意の組み合わせも可能となっています。
%%:スキップ
%p:プロセスID
%u:ユーザID
%g:グループID
%s:シグナル
%t:発生時刻
%h:ホスト名
%e:プロセス名

そして、%pでなく、core_uses_pid(/proc/sys/kernel/core_uses_pidの値)が0でない時、プロセスIDが拡張子として付加されます。このファイル名は、filp_open()で作成されますので、%による変換/拡張子を考慮した64文字ないでの絶対パスで記述すれば、そこにコアファイルが作成されます。

fedora16の初期設定では、/proc/sys/kernel/core_patternは、パイプでabrt-hook-ccppにコアを吐くようになっていて、その旨をメンテナーに通知する仕組みを施しているようですが、filp_open()に"|ファイル名"という形態の引数が可能ってこと? filp_open()をざくっと追ってみましたが、そのような処理されてなかった。でも動作してるってことは、どこかで処理されてるのでしょうが・・・?
[root@localhost kitamura]# cat /proc/sys/kernel/core_pattern
|/usr/libexec/abrt-hook-ccpp %s %c %p %u %g %t e

追記

パイプの機能は、カーネル 2.6.19 以降のカーネルでサポートされていると言う事のようです。私が見ているのは2.6.0です。もしfilp_open()内でパイプの処理をインプリメントしているのなら、sys_open()もfilp_open()をコールしていますので、ユーザプロセスからも同じような入出力が可能ではと思います・・・。宿題ということで。

パイプの処理は入出力先のコールバック関数を差し替えるだけなのですが、パイプ先は標準入出力とし、従って以降のファイルは、読み書きファイルでなく実行させる必要があります。

最終更新 2013/04/20 16:45:44 - north
(2013/04/19 17:44:45 作成)