【问题标题】:Shared memory not getting updated synchronously共享内存未同步更新
【发布时间】:2019-10-25 09:53:58
【问题描述】:

对于我的项目,我有两个任务 1)Writer : 将值写入共享内存的结构中 2)Reader:从结构中读取值

这是编写器代码

struct test {
    volatile int read;
    volatile int write;
};

int main() 
{ 
    // ftok to generate unique key 
    key_t key = ftok("shmfile",65); 

    // shmget returns an identifier in shmid 
    int shmid = shmget(key,1024,0666|IPC_CREAT); 

    // shmat to attach to shared memory 
    struct test *t = (struct test *) shmat(shmid,(void*)0,0); 
    printf("Going to write into test structure"); 

    t->read = 1;
    t->write = 2;

    //printf("Data written in memory: %s\n",str); 

    //detach from shared memory 
    shmdt((void *)t); 

    return 0; 
} 

这是阅读器代码

int main() 
{ 
    // ftok to generate unique key 
    key_t key = ftok("shmfile",65); 
    // shmget returns an identifier in shmid 
    int shmid = shmget(key,1024,0666|IPC_CREAT); 

    // shmat to attach to shared memory 
    struct test *t = (struct test *) shmat(shmid,(void*)0,0); 
    printf("Data read from memory: %d:%d\n",t->read,t->write); 

    //detach from shared memory 
    shmdt((void *)t); 

    // destroy the shared memory 
    shmctl(shmid,IPC_RMID,NULL); 

    return 0; 
} 

当我先运行 writer 然后运行 ​​reader 时,一切正常。

但为了调试,我尝试通过 lldb 同时运行两者。我看看作者是否写了 t->read = 1 ,同时它不会在阅读器进程中得到更新。如果在更改完成后调用 shmat,它将反映在阅读器中。

谁能告诉我,如何确保共享内存中的更改同步发生?

【问题讨论】:

  • 这些演员表有什么用?
  • 您能详细说明一下吗?哪个演员?
  • 全部。而且您需要一个信号量或互斥锁来同步读取和写入。
  • ... 其中,除了同步之外,信号量更适合确保编写者先行。

标签: c linux synchronization ipc shared-memory


【解决方案1】:
   "It would reflect in reader if it calls shmat after changes are done."

我认为在读取器和写入器进程中调用 shmat 的顺序并不重要。唯一需要确保的是在读取器进程开始读取之前将某些内容写入共享内存。这可以使用通常的 IPC 机制来实现,例如 cmets 部分中所述的信号量。我使用 GDB 测试了您的代码。我首先使用 gdb 执行了 writer 进程,并在 't->read = 1;' 之后暂停了 writer 进程陈述。此时我执行了 reader 进程,它成功读取了值 1。

我进行了一些其他测试,其中读取器进程在写入器进程之前调用 shmat,并发现了类似的结果。

我想在这里指出的唯一一点是,只要写入发生在读取之前,调用 shmat 的顺序应该无关紧要。

我在这里添加对您的 cmets 的响应,因为它有点太长,不适合 cmets 部分:

我已经尝试了您建议的步骤并得到了预期的结果,即阅读器进程中't->read'的值为1。我正在使用以下命令来编译我的代码:gcc -g -o writer write。 c 和 gcc -g -o reader read.c 。选项 -g 用于启用调试符号。在此之后,我使用 gdb 来运行编写器和读取器进程,并在 printf 语句处添加断点。因此读取器和写入器进程都在 printf 语句处暂停。然后我在 writer 中执行了 't->read = 1'。在此之后,我检查了两个进程中的内存转储。两者都反映了 1。接下来我打印了 t->read in reader process 的值,它正确显示了 1。

【讨论】:

  • 感谢您的测试。如果你先启动 Producer,那么上去 "t->read = 1;"然后开始消费者,一切都会好起来的。但是如果你按照下面的顺序,事情就行不通了。 1)同时启动生产者和消费者,并在 shmat 之后执行 printf。 2) 然后在生产者中执行 t->read = 1 3) 在消费者中打印 t->read 的值。现在我看到消费者中的 t->read 值仍然为零顺便说一句,我使用以下命令编译代码 cc -pthread -o cons cons.c cc -pthread -o prod prod.c
猜你喜欢
  • 2012-12-31
  • 2012-04-27
  • 1970-01-01
  • 1970-01-01
  • 2014-04-08
  • 2019-10-22
  • 2019-06-03
  • 1970-01-01
  • 2018-09-23
相关资源
最近更新 更多