在我的程序中忽略sem_wait

时间:2014-01-09 02:13:25

标签: c linux semaphore shared-memory

我在linux上的共享内存上写了一个简单的项目。两个程序共享内存,一个是写信,第二个是从中读取。我决定使用信号量,以确保在读取之前不会产生新的字母。

问题是我的编写器进程在其值为0时忽略sem_wait(读取)并且应该等待。它在读者开始之前就完成了它的工作。我通过./writer & ./reader运行它。

我附上了代码。这里有一些未使用的元素,因为它还不是最终版本。但问题已经出现了。

/* writer.c */
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <unistd.h>
#include <stdlib.h>
#include <semaphore.h>

int main( int argc, char *argv[] )
{
    key_t shmkey = 0xF00;
    int bytes = sizeof(char)*3 + sizeof(sem_t) * 3;
    int shmid;
    char* sharedMemory;
    sem_t *writing, *reading, *working;

    if ( (shmid = shmget( shmkey, bytes, IPC_CREAT | IPC_EXCL | 0666 )) < 0 )
    {
        shmdt( (void*) sharedMemory );
        shmctl( shmid, IPC_RMID, NULL );
        return 1;
    }
    if ( (sharedMemory = (char*) shmat( shmid, NULL, 0 )) == (char*) -1 )
    {
        shmdt( (void*) sharedMemory );
        shmctl( shmid, IPC_RMID, NULL );
        return 1;
    }

    writing = (sem_t*)(sharedMemory + 3);
    reading = writing + 1;
    working = reading + 1;

    sem_init( writing, 0, 0 );
    sem_init( reading, 0, 0 );

    sharedMemory[2] = 'w'; // writer is running
    char c;
    for( c = 'a'; c <= 'z'; ++c )
    {
        *sharedMemory = c;
        sem_post( writing );
        sem_wait( reading );
    }
    sharedMemory[2] = 'q';
    while ( sharedMemory[2] != 'w' );
    sharedMemory[2] = 'q';
    shmdt( (void*) sharedMemory );
    shmctl( shmid, IPC_RMID, NULL );
    return 0;
}

读者,

/* reader.c */
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <unistd.h>
#include <stdlib.h>
#include <semaphore.h>

int main( int argc, char *argv[] )
{
    key_t shmkey = 0xF00;
    int bytes = sizeof(char)*3 + sizeof(sem_t) * 3;
    int shmid; 
    char* sharedMemory;
    sem_t *writing, *reading, *working;

    sleep(1); // wait until writer allocates fresh memory
    if ( (shmid = shmget( shmkey, bytes, 0666 )) < 0 )
    {
        shmdt( (void*) sharedMemory );
        return 1;
    }
    if ( (sharedMemory = (char*) shmat( shmid, NULL, 0 )) == (char*) -1 )
    {
        shmdt( (void*) sharedMemory );
        return 1;
    }

    if ( sharedMemory[2] != 'w' ) // is writer running?
    {
        shmdt( (void*) sharedMemory );
        return 1;
    }

    writing = (sem_t*)(sharedMemory + 3);
    reading = writing + 1;
    working = reading + 1;

    //sleep(5); //@REMOVE

    char c;
    do
    {
        sem_wait( writing );
        c = *sharedMemory;
        sem_post( reading );
        printf( "%c\n", c );
    } while ( sharedMemory[2] == 'w' ); 
    sharedMemory[2] = 'w';
    shmdt( (void*) sharedMemory );
    return 0;
}

1 个答案:

答案 0 :(得分:1)

sharedMemory + 3未正确对齐sem_t类型。由于您不知道sem_t的对齐要求,因此您需要确保sem_t对象从共享内存段中的偏移量开始,该偏移量是sizeof(sem_t)的倍数(此因为任何对象的对齐要求均匀地划分其大小,所以可以工作。

请注意,您应该检查sem_waitsem_post的返回值。然后你可以检查errno是否失败,这会告诉你他们失败的原因(但在你的情况下我怀疑errno值可能没有帮助)。