2011-01-12 19 views
1

私はUNIX FIFOで作業を始めました。最初のFIFOプログラムで何かを発見しました。プログラムはこのように動作します:FIFOを作成した後、fork()関数を使用して2つのプロセスが開始されます。子プロセスは、父親がFIFOを介して渡した内容を読み取り、スクリーンに表示します。交換されるデータは、引数として指定された文字列です。問題は、父のセクションで、FIFOの入力側を閉じることを忘れた場合(つまり、close(fd)行を除外した場合)、プロセス間のデータが正しく交換されたとしてもプログラムはハングするだけです。それ以外の場合は、すべて正常に動作し、プログラムは終了時に終了します。誰かがなぜ私を説明できますか?UNIX FIFO:fifoの入力側を閉じないとプロセスがハングアップする

ご理解いただきありがとうございます。利用可能であるか、またはチャネルが他方の端部で閉鎖されている文字があるまで

int main(int argc, char *argv[]) 
{ 
    if(argc != 2) 
    { 
     printf("An argument must be specified\n"); 
     return -1; 
    } 

    int ret = mkfifo("./fifo.txt", 0644); 
    char buf; 

    if(ret < 0) 
    { 
     perror("Error creating FIFO"); 
     return -1; 
    } 

    pid_t pid = fork(); 

    if(pid < 0) 
    { 
     perror("Error creating child process"); 
     return -1; 
    } 

    if(pid == 0) /* child */ 
    { 
     int fd = open("./fifo.txt", O_RDONLY); /* opens the fifo in reading mode */ 

     while(read(fd, &buf, 1) > 0) 
     { 
      write(STDOUT_FILENO, &buf, 1); 
     } 
     write(STDOUT_FILENO, "\n", 1); 
     close(fd); 
     return 0; 
    } 
    else /* father */ 
    { 
     int fd = open("./fifo.txt", O_WRONLY); /* opens the fifo in writing mode */ 

     write(fd, argv[1], strlen(argv[1])); 
     close(fd); 
     waitpid(pid, NULL, 0); 
     return 0; 
    } 
} 
+2

父親がFIFOを閉じるのを待っているので子プロセスがスタックすることはありますか?父親はそれをしないので、子供はFIFOが閉じられるのを永遠に待っています。子供は終了する? – matteoamc

答えて

5

read(2)ブロック:ここでの主な機能のコードがあります。最後の子read()が戻るために、父親のプロセスはパイプを閉じる必要があります。父親のclose(fd)を省略すると、父親が退室(自動的にパイプを閉鎖)するまで子供はread()でブロックされますが、父親は子供が退室するまでwaitpid()にハングします。

+0

もちろん、あなたは正しいです、どうすれば前にそれを得ることができます! read()関数は、FIFOの反対側の親プロセスがそれを閉じるまで0を返しません。ご助力ありがとうございます! – matteoamc

0

最初のもの:投稿したコードにいくつかの問題があります。

  1. #includeディレクティブはありません。したがって、呼び出す関数のスコープにはプロトタイプはありません。 C89には、printf()などの可変関数のプロトタイプが必要です。 C99には、すべての関数のプロトタイプが必要です。 C89とC99の両方とも、O_RDONLY,O_WRONLY,STDOUT_FILENOおよびNULLの範囲の宣言が必要です。
  2. -1は、main()の許可された戻り値ではありません。
  3. C89では、宣言とステートメントを混在させることはできません。

マイナーニト:通常の用語は「父と子」ではなく「親と子」です。

私はこの問題を修正し、読みやすさを向上させるために、あなたのプログラムを変更した:

#include <sys/types.h> 
#include <sys/stat.h> 
#include <sys/wait.h> 

#include <fcntl.h> 
#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 

int 
main(int argc, char *argv[]) 
{ 
    if (argc != 2) { 
     printf("An argument must be specified\n"); 
     return 1; 
    } 

    int ret = mkfifo("./fifo.txt", 0644); 
    char buf; 

    if (ret < 0) { 
     perror("Error creating FIFO"); 
     return 1; 
    } 

    pid_t pid = fork(); 

    if (pid < 0) { 
     perror("Error creating child process"); 
     return 1; 
    } 

    if (pid == 0) { /* child */ 
     int fd = open("./fifo.txt", O_RDONLY); /* opens the fifo in reading mode */ 

     while(read(fd, &buf, 1) > 0) { 
      write(STDOUT_FILENO, &buf, 1); 
     } 
     write(STDOUT_FILENO, "\n", 1); 
     close(fd); 
     return 0; 
    } else { /* parent */ 
     int fd = open("./fifo.txt", O_WRONLY); /* opens the fifo in writing mode */ 

     write(fd, argv[1], strlen(argv[1])); 
     close(fd); 
     waitpid(pid, NULL, 0); 
     return 0; 
    } 
} 

しかし、最も重要なのは、あなたが使用しているオペレーティングシステムとコンパイラ言及しませんでした。

問題を再現できないため、上記のいずれかの問題が発生している可能性があります。

+0

誰がC89 – JeremyP

+0

Bahだと言ったのですが、問題を再現できません - 指定した 'close()'文を削除するのではなく、プログラムをコンパイルして実行しました。 JeremyPが言ったこと。 – DES

+0

JeremyPでは、それはC89かC99のどちらか、またはどちらか一方から得られたある方言です。どちらの場合でも、プログラムは、 'O_RDONLY'、' O_WRONLY'、 'STDOUT_FILENO'、' NULL'の宣言(またはマクロ定義)がないため、コンパイラを最も寛容にしても列挙されたようにコンパイルされません。 – DES

関連する問題