【问题标题】:C Reader Writer Program, One reader isnt reading all the dataC Reader Writer Program,一个阅读器不读取所有数据
【发布时间】:2020-02-01 18:36:30
【问题描述】:

我正在开发一个读写器程序,其中一个作者对 n 个读者。我遇到了一个问题,如果有多个阅读器,就像下面发布的屏幕截图一样,那么共享内存中的整个消息都不会显示。

输出

输入消息:测试

Reader1:测试

Reader2:测试

作者:测试测试

Reader1:测试

Reader2:测试测试

作家

读者

我试图添加一个计数变量,因为我假设在所有阅读器都能够打印之前,作者轮到被标记,它使作者然后退出编写器中的嵌套 while() 并阻止阅读器打印.

关于让读者都打印的任何建议,无论是旗帜还是某种计数?下面还附上 writer 和 reader 循环的屏幕截图。

读者:

int main() {
    DataShared data;
    data.turn = 0;
    signal(SIGINT, sigHandler);

    //generates key
    key = ftok("mkey",65);

    //returns an identifier in mId
    if ((mId = shmget(key, SIZE, IPC_CREAT|S_IRUSR|S_IWUSR)) < 0){
    perror("shared memory error");
    exit(1);
    }

    // shmat to attach to shared memory
    if((mPtr = shmat(mId, 0, 0)) == (void*) -1) {
    perror("Can't attach\n");
    exit(1);
    }


    while(1) {
        // request critical section
        while(!data.turn && data.count == 0) {
        //not time for the reader, check if token is changed.
            memcpy(&data, mPtr, sizeof(DataShared));
        }

        data.count++;

        // enter critical section
        usleep(1);
        fprintf(stderr, "Read from memory: %s\n", data.message);
        usleep(1);
        // leave critical section

        data.count--;

        while(data.count > 0){
            ;
        }

        data.turn = 0;
        memcpy(mPtr, &data, sizeof(DataShared));
    };

    return 0;
}

作者:

int main() {
    DataShared data;
    data.turn = 0;
    data.count = 0;
    signal(SIGINT, sigHandler);

    key = ftok("mkey",65);

    if((shmId = shmget(key, SIZE, IPC_CREAT|S_IRUSR|S_IWUSR)) < 0 ) {
        perror("Error creating shared memory\n");
        exit(1);
    }

    if((shmPtr = shmat(shmId, 0, 0)) == (void*) -1) {
        perror("Can't attach\n");
        exit(1);
    }

    while(1) {
        while (data.turn) {
            memcpy(&data, shmPtr, sizeof(DataShared));
        }

        // enter critical section
        printf("Enter a message: \n" );
        fgets(data.message, 1024, stdin);


        // leave critical section
        printf("Message written to memory: %s\n", data.message);
        data.turn = 1;
        memcpy(shmPtr, &data, sizeof(DataShared));
    };

    return 0;
}

【问题讨论】:

  • 请删除图片并替换为文字。
  • @500-InternalServerError 我正在尝试在没有信号量或线程的情况下执行此操作。
  • @PaulOgilvie 不会因为标志永远不会保存到共享内存而改变从作者到读者的转变吗?
  • 这里的排程看不懂。
  • 请向我们展示您的主要内容,您从哪里开始阅读器和作者。

标签: c reader writer


【解决方案1】:

这可能不是对你观察的解释,但你所做的很可疑。

您有多个进程,操作系统会调度每个进程。

首先,不能保证所有读者都会阅读该消息。很可能一个读取器完成,将标志设置为 0 并将数据复制回共享内存,然后另一个读取器有机会读取数据。

然后你的data.count。它以作者的局部变量data 开头。在那里你没有初始化data.count,所以它有一个不确定的值。在阅读器中,您将其设置为 0,但它将被共享内存中的值(不确定值)覆盖。你做一个 ++,然后是一个 -- 然后等待它变成 0。它怎么会变成 0?那位读者可以永远等待。

【讨论】:

  • 您指出的第一个问题是我添加计数的原因,这是为了测试以确保所有读者都打印出来,然后作者才能再次访问。以当前方式实现的 count 变量的问题也是已知的,我再次在 Writer 中测试了它的初始化,但没有运气。这个问题绝对是我最好的:)
  • 我没有看到你在编写器中初始化data.count
  • 将问题更新为 data.count 在 writer 中的初始化位置
  • 好的。关注data.count++;,不应该把它复制回共享内存吗?否则没人会看到。这可能会导致其他同步问题....
  • 共享内存上的memcpy 是否保证原子性?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-15
  • 2018-02-01
相关资源
最近更新 更多