2011-07-29 10 views
2

次のコード例は実行されますが、フォークされたプロセスからの出力は読み込めません。Enterを押してから「読み込みに失敗しました」までは何も表示されません。示しています。fork()のプロセス内のIOストリーム

質問:それはなぜですか、fork()のプロセスからstdinstdoutと対話するにはどうすればよいですか?

/* example1.c */ 

#include <sys/types.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <fcntl.h> 

int main() { 
    pid_t pid = fork(); 

    if (!pid) { 
     // child 

     char s[64]; 
     printf("Enter something: "); 
     char *res = fgets(s, 64, stdin); 
     if (!res) { 
      printf("Read failed!\n"); 
     } else { 
      printf("You entered: %s", s); 
     } 
    } 

    return 0; 
} 

更新:IOの奇妙な行動の別の例は、ストリーム

/* example2.c */ 

#include <sys/types.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <fcntl.h> 

int main() { 
    pid_t pid = fork(); 

    if (!pid) { 
     // child 

     char *argv[] = { 
      "-c", 
      "/home/user/echo.sh", 
      NULL 
     }; 

     execv("/bin/sh", argv); 
    } 
    return 0; 
} 

echo.shスクリプト:

#!/bin/sh 

read -p "Enter something: " INPUT 
echo "You entered $INPUT" 

この1つは

を返します。
Enter something: /home/user/echo.sh: line 3: read: read error: 0: Input/output error 
You entered 

アップデート2:

は、このコードが必要なのは、正確に何を次のようになります。

#include <sys/types.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <fcntl.h> 

int main() { 
    pid_t pid = vfork(); 
    if (!pid) { 
     // child 
     system("/home/user/echo.sh"); 
    } 
    return 0; 
} 

ソリューションはvforkforkを交換しました。私はちょうどなぜこれが働いているのか分かりません...

+0

おそらく、親が子が終了する前に終了していますか? –

+0

@ 0A0D:ありがとう、これがそうであるように、問題は 'fork()'/'execv'の代わりに' system() 'を使って簡単に解決できます。しかし、IOストリームを継承する別のプロセスで実行可能ファイルをどのように起動するのですか?私は子供が出るのを待つことなく、いつでも親プロセスを殺すことができる必要があります。 – Andy

+2

@Andy - 'vfork'は、子プロセスが終了するまで呼び出しプロセスを中断します。これは親プロセスで 'wait'を呼び出すのとまったく同じです。 – Seth

答えて

0

UNIX/Linuxの場合、stdoutがコンソールに入ると、それはラインバッファです。

  • fflush(stdout)
  • prinf("\n")
  • 標準出力バッファオーバーフローを:それはあなたがいずれかを実行するまで何も出力されない、です。つまり、stdoutが(ファイルのパイプのように)どこか別の場所に行く

それは完全にバッファリングされ、printf("\n")はバッファをフラッシュしません。

+0

これは、 'stdin'からの読み込みエラーの問題を解決しません。 – Andy

+0

最初のステップは、読み込みが失敗したときに 'errno'のエラーコードをチェックすることです。 –

2

私はあなたがほしいと思うと思うwait(2)。あなたの子プロセスがどのプロセスが(ジョブ制御を行うことになっている)シェルの直接の子でない孤立したプロセスグループ、に今あるので

/* example1.c */ 

#include <sys/types.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <fcntl.h> 

int main() { 
    int status; 
    pid_t pid = fork(); 

    if (!pid) { 
     // child 

     char s[64]; 
     printf("Enter something: "); 
     char *res = fgets(s, 64, stdin); 
     if (!res) { 
      printf("Read failed!\n"); 
     } else { 
      printf("You entered: %s", s); 
     } 
    } 
    else 
    { 
     while (wait(&status) != pid); 
    } 
    return 0; 
} 
+0

ありがとう、ありがとう。しかし、私が必要とするのは、終了するのを待たずに、バックグラウンドで外部プログラムを実行することです。しかし、すでに述べた@ 0A0Dのように、あなたのソリューションは、子プロセスが終了するまでストリームが閉じないようにします。 – Andy

+0

または、単にwait()の代わりに '_exit(0)'を呼び出してください。 –

+0

@Maxim:できません:fork()とparentの間には他にもたくさんのコードがあるので、 '_exit'を呼び出すと、' exit '不可能だと思われる。 – Andy

1

のようです。

孤立したプロセスグループ:はプロセスグループではなく、同じセッション(〜シェルの直接の子である)内の親を持っていない、少なくともメンバーを持っていませんプロセスグループ。

親と子の両方で実行されているが、状況はこのようなものです:

$ ps fax -o pid,pgid,sid,ppid,tty,stat,time,cmd 
27177 27177 27177 32170 pts/6 Ss 00:00:00 | \_ /bin/bash 
4706 4706 27177 27177 pts/6 S+ 00:00:00 |  \_ ./ex1 
4707 4706 27177 4706 pts/6 S+ 00:00:00 |   \_ ./ex1 

プロセスグループ上の2つのプロセス、4706と4707 4706 4706があることである、27177の子であります同じセッション(27177)、異なるプロセスグループ(27177):プロセスグループ4706のジョブ制御を扱うシェルです。親が死ぬと

は、状況はこのようなものです:

$ ps fax -o pid,pgid,sid,ppid,tty,stat,time,cmd 
27177 27177 27177 32170 pts/6 Ss+ 00:00:00 | \_ /bin/bash 
4664 4663 27177  1 pts/6 S 00:00:00 ./ex1 

のみプロセスグループ4663、およびその親(INIT)で一つのプロセス、4664は、同じセッション上ではありませんがあります。シェルはこのプロセスグループのジョブ制御を処理できないため、read()write()EIOです。

関連する問題