多个进程中的Reader-Writer C

时间:2014-08-14 14:21:57

标签: c multithreading semaphore

我有一个C程序,父进程创建一个读者线程,然后分叉子进程,子进程创建多个编写器线程。

Writer线程正确地将元素插入到共享缓冲区中,但读者线程并没有做任何事情!当我将所有读写器线程放在一个进程中时,程序正常工作,读取器从缓冲区中读取元素!读者和作者都使用sem_t作为信号量,使用sem_waitsem_post来管理对缓冲区的访问。

这是我的程序伪代码:

int main()
{
initialize semaphores

create reader_thread(reader code)

fork child process(server)
}

int server()
{
create writer threads(writer code)
}

这是缓冲结构:

typedef struct
{
    Req_info reqinfo[BUFFER_SIZE];
    char chunk[BUFFER_SIZE][MAX_CHUNK_SIZE];
    uint64_t chunk_size[BUFFER_SIZE];
    int Isnewfile[BUFFER_SIZE];     //1 means new file
    int Islastchunk[BUFFER_SIZE];   //1 means last chunk
    int ID[BUFFER_SIZE];
    int head;
    int tail;
    int numofelement;
#ifdef SEM_V
    sem_t full;
    sem_t empty;
    sem_t mutex;
#else
    pthread_mutex_t mutex;
    pthread_cond_t cond_read;
    pthread_cond_t cond_write;
#endif
} Buffer;

Buffer *buffer_ptr;


void writer()
{
#ifdef SEM_V
    sem_wait(&buffer_ptr->empty);
    sem_wait(&buffer_ptr->mutex);
#else
    pthread_mutex_lock(&buffer_ptr->mutex);

    if((buffer_ptr->tail + 1) % BUFFER_SIZE == buffer_ptr->head)
    pthread_cond_wait( &buffer_ptr->cond_write, &buffer_ptr->mutex );

    pthread_mutex_unlock(&buffer_ptr->mutex);

    pthread_mutex_lock(&buffer_ptr->mutex);
#endif

    if ((buffer_ptr->tail + 1) % BUFFER_SIZE != buffer_ptr->head)
    {

    memmove(buffer_ptr->chunk[buffer_ptr->tail], chunk, chunk_size);    //Write chunk into buffer
    buffer_ptr->chunk[buffer_ptr->tail][chunk_size] = '\0';

    buffer_ptr->chunk_size[buffer_ptr->tail] = chunk_size;          //Write chunk size into buffer

    buffer_ptr->Isnewfile[buffer_ptr->tail] = Isnewfile;

    buffer_ptr->Islastchunk[buffer_ptr->tail] = Islastchunk;

    buffer_ptr->reqinfo[buffer_ptr->tail] = reqinfo;

    buffer_ptr->ID[buffer_ptr->tail] = ID;

    buffer_ptr->tail = (buffer_ptr->tail + 1) % BUFFER_SIZE;

    }
#ifdef SEM_V
    sem_post(&buffer_ptr->mutex);
    sem_post(&buffer_ptr->full);
#else

    pthread_cond_signal(&buffer_ptr->cond_write);
    pthread_mutex_unlock(&buffer_ptr->mutex);
#endif
}


void reader()
{
#ifdef SEM_V
        sem_wait(&buffer_ptr->full);
#endif

        if (buffer_ptr->tail != buffer_ptr->head)
            {

        if(!first){
            gettimeofday(&ts, NULL);
            first = 1;
        }

        chunksize = buffer_ptr->chunk_size[buffer_ptr->head];           //Read chunk size from buffer

        memmove(chunk, buffer_ptr->chunk[buffer_ptr->head], chunksize);     //Read chunk from buffer
        chunk[chunksize] = '\0';

        Isnewfile = buffer_ptr->Isnewfile[buffer_ptr->head];
        Islastchunk = buffer_ptr->Islastchunk[buffer_ptr->head];

        reqinfo = buffer_ptr->reqinfo[buffer_ptr->head];

        ID = buffer_ptr->ID[buffer_ptr->head];

            buffer_ptr->head = (buffer_ptr->head + 1) % BUFFER_SIZE;

            }
        else{
#ifdef SEM_V
        sem_post(&buffer_ptr->empty);
#endif
        continue;
        }
#ifdef SEM_V
        sem_post(&buffer_ptr->empty);
#endif
}

1 个答案:

答案 0 :(得分:1)

这里至少有两个问题:1)父进程和子进程之间是否共享sem_t full/empty/mutex; 2)缓冲区是否在父进程和子进程之间共享。

1)由于子进程驻留在单独的地址空间中,因此它不再与父进程共享相同的sem_t。所以你需要明确地让这些信号量被共享。结果,读写器无法正确同步。您可以参考this post了解如何共享信号量。

2)同样由于copy-on-write机制,父进程中的reader线程和子进程中的writer线程在fork之后不再共享相同的缓冲区。因此,您还需要显式共享父级和子级之间的缓冲区。有several ways来做这件事。

在您的情况下,由于您的struct Buffer包含信号量和缓冲区,您只需要将其共享,这将解决1)和2)。