2012-03-26 5 views
4

特に、子プロセスを生成する関数を作成する必要があります。 私はこの機能にファイルディスクリプタのオプションのリストを渡したいので、ユーザーのニーズに応じて、子プロセスの入出力をリダイレクトすることができます。フォークされたプロセス出力をNULLにリダイレクト

私はこのようなややこの使用dup2を行う方法について話して数十人を見てきました:

if(pid < 0) // error forking. 
{ 
//... 
} 
else if(pid != 0) // Parent process. 
{ 
    ret = waitpid(pid, &status, 0); 
    return WEXITSTATUS(status); 
} 
else // Child process. 
{ 
    dup2(fd, STDIN_FILENO); // Clone passed file discriptor. 
    close(fd);   // Close the passed one, since we have already cloned. 
    execvp(arglist[ 0 ], arglist); 
} 

よし。これはすべてインターネットにあります。 私の質問は今、どのように/dev/nullにリダイレクトするのですか(または何が最良の方法ですか)ですか?

ユーザーにopen(/dev/null)を強制し、fdとして渡すか、それとも良い方法がありますか?


EDIT:

これは私が望んでいたほどきれいではありませんが、私は任意のより良い方法を見つけることができませんでしたので、私は、ユーザーがリダイレクトする可能性がどこにファイル名の配列を渡してしまいました、それぞれ、STDIN、STDOUTとSTDERR:それはいくつかのバグを持っているかもしれので、私はまだ完全には、それをテストしていません

static int do_exec(arglist_t arglist, const char *fio[ 3 ]) 
{ 
DEBUG__(OSU_DEBUG_LEVEL_1, "fio = %p\n", fio); 

    if (fio) 
    { 
     if (fio[ STDIN_FILENO ]) 
     { 
      int fd = open(fio[ STDIN_FILENO ], O_RDONLY); 

      if (-1 < fd) 
      { 
       dup2(fd, STDIN_FILENO); 
       close(fd); 
      } 
     } 

     if (fio[ STDOUT_FILENO ]) 
     { 
      int fd = open(fio[ STDOUT_FILENO ], O_WRONLY | O_CREAT | O_APPEND); 

      if (-1 < fd) 
      { 
       dup2(fd, STDOUT_FILENO); 
       close(fd); 
      } 
     } 

     if (fio[ STDERR_FILENO ]) 
     { 
      int fd = open(fio[ STDERR_FILENO ], O_WRONLY | O_CREAT | O_APPEND); 

      if (-1 < fd) 
      { 
       dup2(fd, STDERR_FILENO); 
       close(fd); 
      } 
     } 
    } 

    return execvp(arglist[ 0 ], arglist); 
} 

@Zackと@gbulmerに本当に感謝します。

答えて

4

あなたは(FD用-1に渡すと/dev/nullを使用し、

// ... same as you have ... 

else // Child process 
{ 
    if (stdin_fd == -1) 
     stdin_fd = open("/dev/null", O_RDONLY); 
    if (stdin_fd == -1) 
     _exit(127); 
    dup2(stdin_fd, STDIN_FILENO); 
    close(stdin_fd); 

    // similarly for stdout and stderr 

    execvp(arglist[0], arglist); 
    _exit(127); 
} 

を行うことを意味し、あなたのAPIの大会としてPSSTそれを持つことができ:、あなたは括弧の内側にスペースを入れるたびに神は子猫を殺します。)

+0

私はこれがうまくいくことは知っていますが、それを行うより良い方法があるのだろうかと思います。 @gbulmerのようなファイル名を以下に示すように使用して、文字列をNULLでテストし、私のAPIにオープンの責任感を持たせることができます。これはどんなファイルにも制限がなくても動作しますが、それはもっと良い方法でなければならないという味をまだ残しています。本当にありがとう! – j4x

+0

「より良い方法」はあなたのように見えますか? – zwol

+0

明示的にパラメータをテストしたり、ファイルを名前などで開く必要がないソリューションを見たいと思っていますが、それは不可能だと思うので、私はあきらめます。私はあなたが示唆していることをやります(私の編集を参照)。ありがとう! – j4x

1

子プロセスは、どのfdをdup2のoldfdとして使用し、どのfdをdup2に使用するかを知る必要があります。

たとえば、なぜfdはdup2がSTDIN_FILENOになるのですか?

子供はオープンfdの情報を必要とし、fdはdup2'dする必要があります。

一般化するには、ファイル名がfdだけでなく、実際のファイル名であるため「/ dev/null」と言う方法があります。

したがって、struct { int oldfd; char* filename; int newfd; }構造体のリストがあり、そのジョブは規則的であり、/ dev/nullは特殊なケースではありません。 oldfdが-1の場合、dup2の代わりにnewfdでファイル名を開きます。

関連する問題