2016-04-17 18 views
2

パイプ上のノンブロッキングI/Oを行うことはできますか? fcntlはO_NONBLOCKの設定に失敗します。 Linuxプログラミングインタフェースの918ページには、 'パイプまたはFIFOからnバイトを読み込むセマンティクス(p)'という表が含まれています。この表は、O_NONBLOCKが有効になっている1つの列を持つパイプとFIFOの動作をリストしていますか?これは、パイプにO_NONBLOCKフラグを設定できることを意味します。これは正しいです?次のコードはフラグを設定できませんが、fcntl(2)はエラーを報告しません。パイプ上のノンブロッキング読み取り

#include <fcntl.h> 
#include <sys/wait.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <unistd.h> 

#define SLEEP 1 

int 
main(int argc, char *argv[]) { 
    pid_t childPid; 
    int pfd[2]; 
    int nread, flags; 
    int c = 'a';  

    setbuf(stdout, NULL); 

    if (pipe(pfd) == -1) { 
     printf("error: pipe"); 
     exit(EXIT_FAILURE); 
    } 

    switch (childPid = fork()) { 
    case -1: 
     printf("error: fork"); 
     exit(EXIT_FAILURE); 
    case 0:   /* child */ 
     if (close(pfd[0]) == -1) { 
      printf("child: close pfd read"); 
      exit(EXIT_FAILURE); 
     } 
     sleep(SLEEP); 
     _exit(EXIT_SUCCESS); 
    default: 
     break; 
       /* parent falls through */ 
    } 
    if (close(pfd[1]) == -1) { 
     printf("parent: close pipe write"); 
     exit(EXIT_FAILURE); 
    } 

    flags = fcntl(pfd[0], F_GETFD); 
    flags |= O_NONBLOCK; 
    if (fcntl(pfd[0], F_SETFD, flags)) 
     perror("fcntl"); 

    /* verify flags set correctly */ 
    flags = fcntl(pfd[0], F_GETFD); 
    if (!(flags & O_NONBLOCK)) { 
     printf("failed to set O_NONBLOCK\n"); 
     exit(EXIT_FAILURE); 
    } 

    wait(NULL); 
    exit(EXIT_SUCCESS); 
} 
+0

これは 'F_GETFD'操作のバグのようです。私はこれが実際に記述子を非ブロックに設定し、操作がブロックしないことを確認しましたが、 'F_GETFD'はまだゼロを返します。 –

答えて

7

パイプとO_NONBLOCKに特別なものはありません。次の例は、期待どおりに動作します。例をもっと読みやすくするために、すべての呼び出しからすべての呼び出しをチェックしませんでした。実際のアプリケーションでは、チェックを行う必要があります。

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

int main() 
{ 
    int fds[2]; 
    pid_t pid; 
    char buf[100]; 

    pipe(fds); 

    pid = fork(); 

    if (pid) 
    { 
     while (1) 
     { 
      memcpy(buf, "abcdefghi\0",10); 
      write(fds[1], buf, 10); 
      sleep(2); 
     } 
    } 
    else 
    { 
     int retval = fcntl(fds[0], F_SETFL, fcntl(fds[0], F_GETFL) | O_NONBLOCK); 
     printf("Ret from fcntl: %d\n", retval); 
     while (1) 
     { 
      ssize_t r=read(fds[0], buf, 10); 
      printf("read: %d\n", r); 

      if (r > 0) 
      { 
       printf("Buffer: %s\n", buf); 
      } 
      else 
      { 
       printf("Read nothing\n"); 
       perror("Error was"); 
       sleep(1); 
      } 
     } 
    } 
} 

私の例を書いた後、私はあなたのコードを検査した:

flags = fcntl(pfd[0], F_GETFD); 
flags |= O_NONBLOCK; 
if (fcntl(pfd[0], F_SETFD, flags)) 

F_SETFLF_SETFDを変更しても、取得操作のためにしてください。次のコマンドは、ファイル ディスクリプタに関連付けられたフラグを操作する

ファイルディスクリプタフラグ :あなたはfile descriptor flagsが、file descriptor status flagsman 3 fcntlから

:-)を変更しないでしょう。現在のところ、そのようなフラグはFD_CLOEXEC、 クローズ・オン・エックス・フラグのみで定義されています。 FD_CLOEXECビットが0の場合、ファイル記述子 はexecve(2)を介して開いたままになります。それ以外の場合は閉じます。

ファイル状態フラグ 各オープンファイル記述)が(2)を開き、おそらくのfcntl(によって修飾によってtialized ini-、特定の関連する状態フラグを有しています。重複したファイル (dup(2)、fcntl(F_DUPFD)、fork(2)などで作成された)記述子は、同じオープンファイル記述 を参照し、同じファイルステータス フラグを共有します。

F_SETFL(int) ファイルステータスフラグをargで指定された値に設定します。 argのファイル アクセスモード(O_RDONLY、O_WRONLY、O_RDWR)とファイル作成フラグ (O_CREAT、O_EXCL、O_NOCTTY、O_TRUNC)は無視されます。 Linuxでは、このコマンドはO_APPEND、O_ASYNC、 O_DIRECT、O_NOATIME、およびO_NONBLOCKフラグのみを変更できます。 は、O_DSYNCフラグとO_SYNCフラグを変更することはできません。以下のバグを参照してください。

+0

良いクラウスクラウス、私はそれが私がやっていた何か愚かな感じだった。あなたの時間をありがとう。 – Tobin

関連する問題