0

以下を機能させるには助けが必要です。

リングバッファに複数のプロデューサー スレッド (それぞれが 100 バイトのデータを書き込む) があります。そして、1 つのリーダー (消費者) スレッドは、一度に 100 バイトを読み取り、stdout に書き込みます。(最後に、データに基づいてファイルに書き込みたい)

この実装では、リングバッファから読み取ったデータが間違っている場合があります。以下参照 リングバッファのサイズが小さいため、いっぱいになり、データの一部が失われます。これは現在の問題ではありません。

** 質問:

  1. リングバッファから読み取ったデータを印刷すると、一部のデータが交換されます!!バグを見つけることができません。
  2. ロジック/アプローチは正しいですか? (または)これを行うためのより良い方法はありますか

ringbuffer.h

#define RING_BUFFER_SIZE  500
struct ringbuffer
{
    char *buffer;
    int wr_pointer;
    int rd_pointer;
    int size;
    int fill_count;
};

ringbuffer.c

#include <stdio.h>
#include <stdlib.h> 
#include <string.h>
#include "ringbuffer.h"

int init_ringbuffer(char *rbuffer, struct ringbuffer *rb, size_t size)
{
    rb->buffer = rbuffer;
    rb->size = size;
        rb->rd_pointer = 0;
        rb->wr_pointer = 0; 
        rb->fill_count = 0;
    return 0;
}

int rb_get_free_space (struct ringbuffer *rb)
{ 
    return (rb->size -  rb->fill_count);
}

int rb_write (struct ringbuffer *rb, unsigned char * buf, int len)
{
    int availableSpace;
    int i;

    availableSpace = rb_get_free_space(rb);
    printf("In Write AVAIL SPC=%d\n",availableSpace);
    /* Check if Ring Buffer is FULL */
    if(len > availableSpace)
    {
       printf("NO SPACE TO WRITE - RETURN\n");
       return -1;
    }

    i = rb->wr_pointer;
    if(i == rb->size) //At the end of Buffer 
    {
       i = 0;
    }    
    else if (i + len > rb->size)
    {
        memcpy(rb->buffer + i, buf, rb->size - i);
        buf += rb->size - i;
        len = len - (rb->size - i);
        rb->fill_count += len;
        i = 0;
    }
    memcpy(rb->buffer + i, buf, len);
    rb->wr_pointer = i + len;
    rb->fill_count += len;

    printf("w...rb->write=%tx\n", rb->wr_pointer );
    printf("w...rb->read=%tx\n", rb->rd_pointer );
    printf("w...rb->fill_count=%d\n", rb->fill_count );
    return 0;
}

int rb_read (struct ringbuffer *rb, unsigned char * buf, int max)
{
    int i;

    printf("In Read,Current DATA size in RB=%d\n",rb->fill_count);
    /* Check if Ring Buffer is EMPTY */
    if(max > rb->fill_count) 
    {
      printf("In Read, RB EMPTY - RETURN\n");
      return  -1; 
    }  

    i = rb->rd_pointer;
    if (i == rb->size)
    {
       i = 0;
    }
    else if(i + max > rb->size)
    {
        memcpy(buf, rb->buffer + i, rb->size - i);
        buf += rb->size - i;
        max = max - (rb->size - i);
        rb->fill_count -= max;
        i = 0;
    }
    memcpy(buf, rb->buffer + i, max);
    rb->rd_pointer = i + max;
    rb->fill_count -= max;

    printf("r...rb->write=%tx\n", rb->wr_pointer );
    printf("r...rb->read=%tx\n", rb->rd_pointer );
    printf("DATA READ ---> %s\n",(char *)buf);
    printf("r...rb->fill_count=%d\n", rb->fill_count );
    return 0;
}
4

3 に答える 3

0

プロデューサーでは、条件の条件変数も待機する必要がありhas empty spaceます。両方の条件付き変数は、無条件に通知する必要があります。つまり、コンシューマーがリング バッファーから要素を削除すると、プロデューサーに通知する必要があります。プロデューサーがバッファーに何かを入れると、コンシューマーに通知する必要があります。また、この待機/シグナリング ロジックを rb_read および rb_write の実装に移動すると、リング バッファはプログラムの残りの部分で「完全に使用できるソリューション」になります。

于 2012-10-25T14:54:14.020 に答える
0

あなたの質問について - 1.私もそのバグを見つけることができません - 実際、私はあなたのコードを試しましたが、その動作は見られません。2. これが論理/アプローチで正しいかどうかを尋ねます。まあ、これは一種のリング バッファを実装しています。あなたのテストケースはたまたまサイズの整数倍であり、レコードサイズは一定であるため、これは最適なテストではありません。

あなたのコードを試してみると、多くのスレッド飢餓があることがわかりました-実行する最初のプロデューサースレッド(最後に作成されたスレッド)が非常に激しくヒットし、最初の5回後にバッファに物を詰め込もうとして失敗しました。消費者スレッドを実行する (または開始することさえ)。次に、消費者スレッドが開始すると、CPU を解放する前にかなりの時間クランキングを続け、最終的に次の生産者スレッドが開始します。それが私のマシンでの動作方法です。異なるマシンでは異なると思います。

あなたの現在のコードが終了する方法を持っていないのは残念です-数十または数百メガバイトのファイルを作成する...苦労するのは難しいです.

于 2012-10-25T16:52:47.283 に答える