【问题标题】:Shared Memory program behaving weirdly共享内存程序行为怪异
【发布时间】:2016-06-14 07:27:09
【问题描述】:

我编写了以下代码,以使 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;
}

将 Read 和 Write 拆分为两个独立进程的原因是为了启用“实时”聊天 - 否则 scanf 将阻止执行,直到输入某些内容。

我还添加了一个简单的锁定机制 - 我知道这里的编写代码并不是真正的原子,但我添加它只是为了模拟锁定。

【问题讨论】:

  • 1) 添加代码以检查来自shmget()shmat() 的返回值,以确保操作成功。 2) 添加代码以检查来自fork() 的返回值何时失败。 3) 完成共享内存后,将指针传递给shmdt()。 4)主进程在退出前必须调用wait()waitpid()。子进程不能调用shmdt()

标签: c unix ipc shared-memory


【解决方案1】:

我认为您需要将 lastRead 设为 volatile。在我看来,一个进程正在缓存该值,而不是从另一个进程获取更新。就这样声明吧

volatile int lastRead = -1;

【讨论】:

  • 我刚刚发现了这个错误。问题在于 handleRead() 方法中的条件。如果条件不满足,lastRead 变量不会增加,因此阅读器会陷入无限循环,什么也不做。感谢您调查我的问题。
猜你喜欢
  • 2013-04-01
  • 2010-11-07
  • 2014-12-12
  • 2013-06-04
  • 2014-10-26
  • 2013-01-08
  • 2019-06-23
  • 2012-03-28
相关资源
最近更新 更多