読み取りバッファサイズが2048の場合は機能しますが、バッファサイズが48または他の数値の場合、書き込み呼び出しはブロックされます。なぜですか?

読み取りバッファサイズが2048の場合は機能しますが、バッファサイズが48または他の数値の場合、書き込み呼び出しはブロックされます。なぜですか?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char* argv[]){
    if(argc < 2){ 
        puts("err argv");
        return -1; 
    }   

    int r_fd = open(argv[1], O_RDWR);
    int w_fd = open(argv[1], O_RDWR);

    fd_set r_set;
    fd_set w_set;
    char w_buf[4096];
    char r_buf[2048];
    int read_count = 0,write_count = 0;  
    while(1){
        FD_ZERO(&r_set);
        FD_ZERO(&w_set);
        FD_SET(r_fd, &r_set);
        FD_SET(w_fd, &w_set);
        int ret = select(w_fd + 1, &r_set, &w_set, NULL, NULL);
        if(FD_ISSET(r_fd, &r_set)){
            read(r_fd, r_buf, sizeof(r_buf));    
            printf("read count:%d\n", read_count++);    
        }   
        if(FD_ISSET(w_fd, &w_set)){
            write(w_fd, w_buf, sizeof(w_buf));
            printf("write count:%d\n", write_count++);  
        }   
        //sleep(1);
    }   

    return 0;
}

実行コード: mkfifo 1.fifo && gcc main.c -o main && ./main 1.fifo

ベストアンサー1

        if(FD_ISSET(w_fd, &w_set)){
            write(w_fd, w_buf, sizeof(w_buf));
            printf("write count:%d\n", write_count++);  
        }   

selectfdが書き込み可能であると言われるならば、これは次のように書くことができるという意味です。最小1バイト。 FIFOバッファの管理方法によっては、しきい値が1より高くなる可能性がありますが、これはブロックなしで4096バイトを書き込むことができるという意味ではありません。

このコードは静的に間違っています。合理的に頑丈にするには、両方のfdを非ブロックモードに設定する必要があります(そして適切にコードを処理EAGAIN/返すために準備する必要があります)。EWOULDBLOCK

これ理由w_fd読み込みバッファサイズが原因で公開される問題のいくつかは、FIFOが十分に空ですが(書き込み可能に見えるように)書き込みを完了するのに十分すぎて(したがってブロック)状況に到達できるかどうかに関するものです。

ブロックされたプロセスにデバッガを接続するか、straceで実行してそれを確認または偽造することができます。これらは使い方を学ぶ必要がある完全に一般的なツールです。

おすすめ記事