2017-04-25 9 views
2

シグナルハンドラでececl()を使用してSIGSEGVを受信したときにプログラムをリセットしようとしています。しかし、私の現在のプログラムでは、execl()と1つの余分な引数"RESTART"を介して渡すことができるコマンドライン引数が必要です。C:実行中のプログラムと同じコマンドライン引数でプログラムをexec()するには

しかし、私はargv []をexec()経由で渡すことができますか?

目的: execl("./myprog","./myprog",argv[1],argv[2],...,argv[argc],"RESTART"); OR execl("./myprog","./myprog","RESTART",argv[1],argv[2],...,argv[argc]);

+6

'execv'を見てください。 –

+4

*「SIGSEGVを受け取ったときにプログラムをリセットしようとしています」*正しい理由でこれをやっていることを願っています... – Ryan

+0

アプリケーションを再起動しようとするのは良い考えではありません。代わりに、アプリケーションをラップするスクリプトを作成し、クラッシュしたときにアプリケーションを再起動することができます。または、システムクラッシュ後に再起動するためにsystemdを使用することもできます。 –

答えて

2

あなたがいずれかのメインから、グローバルにARGVを保存する必要があります。

static char **Argv; 
__attribute__((constructor)) 
static void ctor(int c, char **v) { Argv = v; } 

は、その後、あなたがやりたいことができます:

#include <stdio.h> 
#include <unistd.h> 
#include <signal.h> 

static char **Argv; 

static void hndlr(int s) 
{ 
    execv("/proc/self/exe", Argv); 
    _exit(127); 
} 
int main(int argc, char **argv) 
{ 
    Argv = argv; 

    struct sigaction sa = { .sa_handler = hndlr, .sa_flags = SA_NODEFER }; 
    sigaction(SIGSEGV, &sa, 0); 

    sleep(1); 
    fputs("start\n", stderr); 

    //keep re-executing the same program 
    raise(SIGSEGV); 
} 
static char **Argv; 
int main(int c, char **v) { Argv = v; //... 

やgccのコンストラクタから

SA_NODEFERがなければ、SIGSEGVは秒間にブロックされるため、メッセージは2回しか表示されません実行可能ファイルの実行。

これを定義する必要がありますが(特にシグナルスタックを追加してスタックオーバーフローもこれで処理できるようにする場合)、ラッパースクリプト/プログラムはこれを実行する上でより安全で堅牢な方法です。 SISEGVハンドラのアプローチでは、シグナルマスク、有効なuid/gid、作業ディレクトリ、開いているファイル記述子などを継承していますが、ラッパースクリプトでは明確に定義されていません状態。

3

Use execv():

SYNOPSIS

#include <unistd.h> 

...

int execv(const char *path, char *const argv[]); 

...

execv()execvp()、およびexecvpe()機能は、新しいプログラムに利用できる引数リスト を表すNULLで終わる文字列へ ポインタの配列を提供しています。慣習的には、最初の引数は で、実行中のファイルに関連付けられたファイル名を指す必要があります。 ポインタの配列は、NULLポインタで終了する必要があります。おそらく、このような

int main(int argc, char **argv) 
{ 
    ... 
    int rc = execv("./myprog", argv); 
} 

あなたはargvに特定の値を変更したり、あなたが必要なものを合わせてまったく新しい引数配列を作成する必要があります。

関連する問題