3

名前付きパイプから読み取らなければならないという問題があります。名前付きパイプへのライターが行き来する状況に対処する必要がありますが、アプリケーション全体で同じパイプを開いたままにしておく必要があります。

これを次のコードにまとめました。

int main( int c, char *v[] )
{
    int rfd;
    if ( (rfd = open( PIPENAME, O_RDONLY | O_NONBLOCK )) < 0 )
    {
        perror( "open" );
        return 1;
    }

    char buffer[ 1024000 ];

    // used to give select an upper bound on number of fds
    int nfd = rfd + 1;

    fd_set rfds;
    FD_ZERO( &rfds );
    FD_SET( rfd, &rfds );

    while( true )
    {
        int nr = select( nfd, &rfds, NULL, NULL, NULL );

        if ( nr < 0 )
        {
            perror( "select" );
            break;
        }

        if ( FD_ISSET( rfd, &rfds ) )
        {
            //std::cout << "RFD SET" << std::endl;
            // Ok, we have data we can read
            int nread = read( rfd, buffer, sizeof( buffer ) );
            if ( nread < 0 )
            {
                perror( "read" );
                break;
            }
            else if ( nread == 0 )
            {
                std::cout << "read 0" << std::endl;
            }
            else
            {
                std::cout << "read " << nread << " bytes" << std::endl;

            }

        }
    }

    close( rfd );

    return 0;
}

私が抱えている問題は、最初のプロセスが名前付きパイプに書き込み、それが終了した後、プログラムが選択をブロックしないことです。事実上、rfdが設定されており、読み取りはタイトループで読み取られたゼロバイトを返します。

rfdをNON_BLOCKINGモードにする必要があります。そうしないと、ライターが表示されるまでopenがブロックされます。

fcntlを使用してBLOCKINGモードに設定しようとしましたが、それも機能しません。

パイプのセマンティクスについての私の限られた理解は、selectがブロックされるようにパイプのEOF状態をクリアする必要があると思います。しかし、これを行う方法がわかりません。

私はあなたの集合的な知恵に身を投じます:)マーク。

4

3 に答える 3

4

OK、私は1つの解決策を考え出しましたが、私はそれについて本当に満足していません。私に言わせれば、それはちょっと「ナッツを割るのがハンマー」です。

.....
else if ( nread == 0 )   
{   
    std::cout << "read 0" << std::endl;   

    FD_ZERO( &rfds );
    close( rfd );
    if ( (rfd = open( PIPENAME, O_RDONLY | O_NONBLOCK )) < 0 )
    {
        perror( "re-open" );
        break;
    }
    FD_SET( rfd, &rfds );
    nfd = std::max( wfd, rfd ) + 1;
}   
else
.....

基本的には、パイプを閉じてから再度開きます。

私はまだより良い解決策を歓迎します。

于 2010-01-19T09:33:04.523 に答える
1

他の投稿で見つかりました:

if ( (rfd = open( PIPENAME, O_RDWR | O_NONBLOCK )) < 0 )

つまり、RDONLYの代わりにRDWRを開くとうまくいくようです...

于 2015-02-05T09:02:32.417 に答える
-1

非ブロッキングモードでfdsを開いてみましたか?また、 /にread()戻ったら、fdでaを実行しましたか?EWOULDBLOCKEAGAINclearerr()

于 2010-01-19T09:41:02.680 に答える