【问题标题】:Do child processes copy entire arrays?子进程是否复制整个数组?
【发布时间】:2011-11-13 15:44:40
【问题描述】:

我正在编写一个基本的 UNIX 程序,该程序涉及相互发送消息的进程。我同步进程的想法是简单地使用一组标志来指示进程是否已到达代码中的某个点。

例如,我希望所有进程都等到全部创建完毕。我还希望他们等到他们都完成相互发送消息后再开始阅读他们的管道。

我知道一个进程在写入之前定义的变量时会执行写时复制操作。

我想知道的是,如果我创建一个标志数组,是复制指向该数组的指针,还是复制整个数组(从而使我的想法毫无用处)。

我还想了解有关进程间通信和进程同步的任何提示。

编辑: 进程正在写入彼此进程的管道。每个进程都会发送以下信息:

typedef struct MessageCDT{
    pid_t destination;
    pid_t source;
    int num;
} Message;

所以,只是消息的来源和一些随机数。然后每个进程都会将消息打印到标准输出:类似于“进程 20 从进程 3 收到 5724244”。

【问题讨论】:

  • 您能发布更多有关流程的信息吗?他们在做什么?你为什么不使用线程?为什么你使用一组标志而不是一个控制所有其他进程的控制进程?
  • @FranziskusKarsunke 对不起,我已经更新了信息。这只是一个家庭作业。多线程不是我正在研究的。您能否详细说明控制过程的工作原理?
  • 嗯...如果是作业你应该自己做^^
  • @FranziskusKarsunke 我只是想理解一个概念,也许还有一些技巧。我不是在寻找实际的代码。

标签: linux unix process fork pipe


【解决方案1】:

Unix 进程有独立的地址空间。这意味着一个人的记忆与另一个人的记忆完全分开。当你调用 fork() 时,你会得到一个新的进程副本。立即从 fork() 返回时,两个进程之间唯一不同的是 fork() 的返回值。两个进程中的所有数据都是一样的,但它们是副本。除非您采取措施共享内存,否则另一个无法知道更新其中的内存。

Unix 中的进程间通信 (IPC) 有很多选择,包括共享内存、信号量、管道(命名和未命名)、套接字、消息队列和信号。如果你用谷歌搜索这些东西,你会发现很多要阅读的东西。

在您的特定情况下,尝试让多个进程等待它们都达到某个点,我可能会使用信号量或共享内存,这取决于是否有某个主进程启动了它们。

如果有一个主进程启动其他进程,那么主进程可以设置信号量,其计数等于要同步的进程数,然后启动它们。然后每个孩子可以递减信号量值并等待信号量值达到零。

如果没有主进程,那么我可能会创建一个共享内存段,其中包含进程计数和每个进程的标志。但是当您有两个或多个进程使用共享内存时,您还需要某种锁定机制(可能又是一个信号量)来确保两个进程不会同时尝试更新共享内存。

请记住,读取没有人写入的管道会阻塞读取器,直到数据出现。我不知道您的流程是做什么的,但也许同步就足够了?如果您有多个进程写入给定管道,则需要考虑的另一件事是,如果写入大于 PIPE_BUF,它们的数据可能会交错。该宏的值和位置取决于系统。

-凯文

【讨论】:

  • 只是让你知道,没有现代 *nix 实际上复制整个地址空间。他们做一个写时复制的事情,安排页表条目,以便两个地址空间指向同一个内存,并且在一个或另一个尝试写入给定页面之前不会进行复制。
【解决方案2】:

整个标志数组似乎都被复制了。当然,在一个或另一个进程写入它之前,它实际上不会被复制。但这是一个实现细节,对各个流程是透明的。就每个进程而言,它们每个都得到一个数组的副本。

有办法避免这种情况发生。您可以将mmapMAP_SHARED 选项一起用于标记所使用的内存。然后每个子进程将共享相同的内存区域。还有 Posix 共享内存(顺便说一句,我认为这是一个可怕的 hack)。要了解有关 Posix 共享内存的信息,请查看 shm_overview(7) 手册页。

但是以这种方式使用内存并不是一个好主意。在多核系统上,并非总是这样,当一个进程(或线程)写入共享内存区域时,所有其他进程都会立即看到写入的值。通常,该值会在 L2 缓存中停留一段时间,并且不会立即刷新。

如果您想使用共享内存进行通信,则必须使用互斥锁或 C++11 原子操作来确保其他进程正确看到写入。

【讨论】:

  • 那么如果一个进程写入数组的一个索引,其他进程不会看到这个变化?
  • @seljuq70:不,他们不会。在fork 调用之后,进程之间不会共享内存,除非你明确地做一些事情来实现它。
  • 嗯,这回答了这个问题。是共享内存,谢谢你的帮助。
  • @seljuq70:即使使用共享内存,您也必须努力确保处理器缓存保持适当同步。共享的标志数组会产生您可能意想不到的奇怪结果。
猜你喜欢
  • 2017-10-21
  • 1970-01-01
  • 1970-01-01
  • 2014-09-23
  • 1970-01-01
  • 2015-10-28
  • 2015-02-12
  • 2016-10-29
  • 2016-09-17
相关资源
最近更新 更多