2016-03-01 86 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变量不会增加,因此读者陷入无限循环无所事事。感谢您查看我的问题。 –