2014-01-09 29 views
1

我在linux中編寫了一個簡單的項目用於共享內存。兩個程序共享內存,一個是給它寫信,另一個是從它讀取它們。我決定使用信號量來確保在讀取之前不會產生新的字母。sem_wait在我的程序中被忽略

問題是我的編寫器進程忽略了sem_wait(讀取),當它的值是0並且它應該等待。它甚至在讀者開始之前完成它的工作。我運行它通過./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

該文檔說,sem_init()的第二個參數應該爲非零值,以便在進程之間共享信號量 - 您似乎會調用未定義的行爲。如果你改變了,會發生什麼? – Notlikethat

+0

@Notlikethat它沒有幫助 –

+0

你也應該檢查返回值 - 在失敗閱讀'errno'會告訴你什麼是錯的。 – Notlikethat

回答

1

sharedMemory + 3沒有正確的sem_t類型一致。由於您不知道sem_t的對齊要求,因此您需要確保sem_t對象在共享內存段的偏移量爲sizeof(sem_t)的倍數處開始(這是可行的,因爲任何對象的對齊要求均勻分割其大小)。

請注意,您應該檢查sem_waitsem_post的返回值。然後你可以檢查errno,如果他們失敗了,那會給你提供他們爲什麼失敗的信息(但是在你的情況下,我懷疑errno的值可能不如幫助)。

+0

我正在檢查他們。他們等於0.所以它似乎sem_init()的作品。 –

+0

我不明白爲什麼要檢查errno。編寫器進程結束並返回0,所以從程序的角度來看不應該有任何錯誤,我是否正確? –

+0

我改變了'bytes = sizeof(sem_t)* 4',據我瞭解,這會創建所需的偏移量。它沒有幫助。 –