2016-03-01 82 views
0

我寫了下面的代碼,使2進程聊天使用共享內存。但我正面臨一些奇怪的問題。共享內存程序行爲怪異

假設您從進程A發送消息,它會顯示在進程B的標準輸出上,並且您可以繼續發送來自進程A的消息而不會出現任何問題。但只要您嘗試從流程B發送消息,一切都會停止。 A上不顯示任何消息。如果您現在嘗試從A發送某些內容,即使這樣也不起作用。更糟糕的是,如果我開始一個新的進程,第二個進程首先會產生大量的垃圾輸出,然後變得無法正常工作 - 無法顯示更多輸出。我真的不明白髮生了什麼事。

#include <sys/types.h> 
#include <sys/ipc.h> 
#include <sys/shm.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <string.h> 

struct message { 
    int senderid; 
    char msg[100]; 
}; 
struct message_q { 
    int write_ptr; 
    int writing; 
    struct message msgbuffer[100]; 
} *pmsgq; 

key_t key; 
int shmid; 

int lastRead = -1; 
void handleRead() { 
    while(1) { 
     while(lastRead+1 != pmsgq->write_ptr) { 
      // don't display our own messages 
      if(pmsgq->msgbuffer[1+lastRead].senderid != getppid()) 
       printf("Remote: %s\n",pmsgq->msgbuffer[++lastRead].msg); 
     } 
    } 
} 

void handleWrite() { 
    char msg[100]; 
    while(1) { 
     scanf("%s", msg); 
     while(pmsgq->writing) 
      ; 
     pmsgq->writing = 1; 
     strcpy(pmsgq->msgbuffer[pmsgq->write_ptr].msg, msg); 
     pmsgq->msgbuffer[pmsgq->write_ptr].senderid = getpid(); 
     pmsgq->write_ptr++; 
     pmsgq->writing = 0; 
    } 
} 

int main() { 
    key = ftok("shared_mem_chat.c",'b'); 
    shmid = shmget(key, sizeof(struct message_q), IPC_CREAT | 0666); 
    pmsgq = (struct message_q*) shmat(shmid, NULL, 0); 
    pmsgq->write_ptr = 0; 
    pmsgq->writing = 0; 

    if(fork() == 0) { 
     handleRead(); 
    } 
    else { 
     handleWrite(); 
    } 
    return 0; 
} 

在兩個單獨的進程中分離讀寫的原因是啓用「實時」聊天 - 否則scanf會阻止執行,直到輸入內容。

而且我還添加了一個簡單的鎖定機制 - 我知道這裏的寫入代碼並不是真正的原子,但我添加它只是爲了讓我們說,模擬鎖定。

+0

1)添加代碼來檢查從'shmget()',''shmat()'返回的值以確保操作成功。 2)添加代碼以檢查從fork()返回的值的失敗時間。 3)當完成共享內存時,將指針傳遞給'shmdt()'。 4)主進程在退出之前必須調用wait()或waitpid()。子進程不能調用'shmdt()' – user3629249

回答

1

我認爲你需要讓lastRead一個volatile。在我看來,像一個進程正在緩存該值,而沒有從另一個進程獲取更新。只要聲明它是這樣的

volatile int lastRead = -1; 
+0

我剛發現這個bug。問題在於handleRead()方法中的條件。如果條件不滿足,lastRead變量不會增加,因此讀者陷入無限循環無所事事。感謝您查看我的問題。 –