コアダンプファイル名は、 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(¤t->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()をコールしていますので、ユーザプロセスからも同じような入出力が可能ではと思います・・・。宿題ということで。
パイプの処理は入出力先のコールバック関数を差し替えるだけなのですが、パイプ先は標準入出力とし、従って以降のファイルは、読み書きファイルでなく実行させる必要があります。