【问题标题】:C shared memory with shmget-shmat not working like expected使用 shmget-shmat 的 C 共享内存无法按预期工作
【发布时间】:2022-01-18 05:46:36
【问题描述】:

我在两个进程之间剪切内存时发现了这种奇怪的行为

代码 1

int main() {


    int *p;
    int shmID=shmget(IPC_PRIVATE,sizeof(int),0666|IPC_CREAT);
    p=shmat(shmID,NULL,0);
    *p=0;
    int pid=fork();
    if(pid>0)
        wait(NULL);

    
    *p=*p+1;
    printf("%d\n",*p);
return 0;

}

输出 1

1
2

如预期的那样

代码 2

int main() {


    int *p;
    int shmID=shmget(IPC_PRIVATE,sizeof(int),0666|IPC_CREAT);
    p=shmat(shmID,NULL,0);
    *p=0;
    int pid=fork();
    if(pid>0)
        wait(NULL);

    *p=0;
    *p=*p+1;
    printf("%d\n",*p);
return 0;

}

输出 2

1
1

当我给剪切变量一个值*p=0 时,它的行为就像它在进程之间没有剪切一样。

【问题讨论】:

  • 一个主要问题(在 both 示例中)是存在数据竞争。从内存读取、递增、写回内存和打印不是原子的。两个程序的行为都是undefined
  • 话虽如此,第二个示例中可能发生的情况是一个进程运行完成,将零写入内存,将其递增为一,然后打印该一。然后另一个进程运行完成,做完全相同的事情:写入零,将其递增到一,然后打印那个。
  • 我更改了代码并添加了`int pid=fork(); if(pid>0) wait(NULL);` 但没有任何改变
  • 这不会改变“运行到完成”的行为。这将使子进程运行完成,然后执行与子进程完全相同的操作(将内存设置为零,递增为一,打印一)。
  • 是的,你是对的......谢谢

标签: c linux


【解决方案1】:

您在这里对fork 的行为做出了假设。您假设在fork 调用之后,两个进程将真正同时运行。

除了代码中固有的竞争条件之外,该假设可能不成立,并且实际上取决于实现。可能是初始进程一直持续到阻塞,然后才运行 forked 进程,这将解释 #2 中的结果以及为什么您在实验中实际上没有遇到竞争条件。

【讨论】:

  • wait() 调用不能确保顺序访问吗?哦,我从cmets上看到fork()/wait()代码是在你回答后加的。没关系!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-22
  • 2013-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-30
相关资源
最近更新 更多