我正在编写一个基本的UNIX程序,它涉及向彼此发送消息的进程。我同步进程的想法是简单地使用一组标志来指示进程是否已到达代码中的某个点。
例如,我希望所有进程都等到它们都被创建完毕。我还希望他们等到他们在开始阅读他们的管道之前完成向对方发送消息之后。
我知道进程在写入先前定义的变量时执行写时复制操作。
我想知道的是,如果我创建一个标志数组,是否会复制指向该数组的指针,或者是否会复制整个数组(从而使我的想法变得毫无用处)。
我还想了解有关进程间通信和进程同步的任何提示。
编辑: 进程正在写入其他进程的管道。每个流程都会发送以下信息:
typedef struct MessageCDT{
pid_t destination;
pid_t source;
int num;
} Message;
所以,只是消息的来源和一些随机数。然后每个进程都会将消息打印到stdout:“进程20从进程3收到5724244”的行。“
答案 0 :(得分:5)
Unix进程具有独立的地址空间。这意味着一个内存与另一个内存完全分开。当您调用fork()时,您将获得该进程的新副本。从fork()返回后,两个进程之间唯一不同的是fork()的返回值。两个过程中的所有数据都是相同的,但它们是副本。除非您采取措施共享内存,否则另一方无法知道更新内存。
Unix中的进程间通信(IPC)有很多选择,包括共享内存,信号量,管道(命名和未命名),套接字,消息队列和信号。如果你谷歌这些东西你会发现很多东西。
在您的特定情况下,尝试让多个进程等待直到它们都达到某一点,我可能会使用信号量或共享内存,具体取决于是否有一些主进程启动了它们。
如果有一个主进程启动其他进程,那么主进程可以设置信号量,其计数等于要同步的进程数,然后启动它们。然后,每个孩子可以递减信号量值并等待信号量值达到零。
如果没有主进程,那么我可能会创建一个共享内存段,其中包含进程计数和每个进程的标志。但是当你有两个或多个使用共享内存的进程时,你还需要某种锁定机制(可能再次是一个信号量)来确保两个进程不会同时尝试更新共享内存。
请记住,读取没有人写入的管道会阻止读者,直到出现数据。我不知道你的进程做了什么,但也许这就足够同步了?如果您有多个进程写入给定管道,则需要考虑的另一件事是,如果写入大于PIPE_BUF,则它们的数据可能会交错。此宏的值和位置取决于系统。
-Kevin
答案 1 :(得分:2)
似乎会复制整个标志数组。它实际上不会被复制,直到一个进程或另一个进程写入它当然。但这是一个实施细节,对各个流程都是透明的。就每个进程而言,它们都获得了数组的副本。
有很多方法可以避免这种情况发生。您可以将mmap
与MAP_SHARED
选项一起用于标志所使用的内存。然后每个子进程将共享相同的内存区域。还有Posix共享内存(我,BTW,认为这是一个可怕的黑客)。要了解Posix共享内存,请查看shm_overview(7)
手册页。
但是以这种方式使用内存并不是一个好主意。在多核系统上,并非总是如此,当一个进程(或线程)写入共享内存区域时,所有其他进程将立即看到值。通常,该值将在L2缓存中挂起一段时间,而不是立即刷新。
如果要使用共享内存进行通信,则必须使用互斥锁或C ++ 11原子操作来确保其他进程正确地看到写入。