到目前为止,我在网上阅读的几乎所有代码和教程都涉及使用互斥体和信号量在线程之间进行同步。它们可以用于进程之间的同步吗?
我想编写如下所示的代码:
void compute_and_print() {
// acquire mutex
// critical section
// release mutex
}
void main() {
int pid = fork();
if ( pid == 0 ) {
// do something
compute_and_print();
}
else {
// do something
compute_and_print();
}
}
是的,这是可能的。有多种方法可以同步不同的进程。也许该领域最流行的互斥解决方案是System V IPC 信号量和共享内存上的原子操作。我建议您阅读 David A Ruslin 的书《进程间通信机制》的第 5 章,或者更好的是阅读整本书。 关于第二个问题,商用硬件上的大多数现代操作系统会将进程放置在不同的地址空间中,尽管进程也可以共享相同的地址空间(请参阅虚拟内存
,内存保护)。无论哪种方式,如果 IPC 机制由内核处理,那么两个进程将引用相同的“内核对象”,正如您所说。在(几乎)没有内核的情况下实现互斥的情况下(例如使用“共享内存”的某种自旋锁),两个进程将引用相同的物理内存,即使它们的虚拟地址可能不同。 希望有帮助。祝你好运!
需要明确的是,POSIX(和 Linux)支持
较旧的 SysV 信号量由 semget
semop
、
semctl
和(有些可选)
ftok
组成。
更现代的“posix”信号量由
sem_open/sem_init
、sem_wait
、
sem_post
、
sem_close
和
sem_unlink
组成。
设置/使用机制和功能非常不同,值得您熟悉两者,看看哪种更适合您的用例。您还可以使用 pthreads 包中的进程共享互斥体。
听起来您正在寻找
这是对 Linux 中的 Sys V IPC 的精彩介绍
您需要命名互斥体/信号量。看看pthread_mutexattr_setname_np
使用的 IBM。需要注意的一件事是,Linux 中的命名互斥体不是 100% 可移植的(即它可能在 Ubuntu 上工作,但不能在 CentOS 等上工作),因此您需要确保您的平台支持它。如果命名互斥体在您的系统上不可用,您可以使用带有一些等待条件的命名管道,甚至本地套接字。正如另一个答案指出的那样,是 SysV IPC。
您首先需要回答的最大问题是您希望您的应用程序如何“跨 Linux 平台”兼容。
互斥体是 pthreads 库的一部分。用户程序通过定义 pthread_mutex_t 类型的全局变量并初始化它来创建互斥对象。例如,
pthread_mutex_t new_mutex = PTHREAD_MUTEX_INITIALIZER;
这里,new_mutex仅在定义它的程序中可见。因此new_mutex可以用来同步运行该程序的进程中的线程。当需要同步进程时,情况略有不同。每个进程都有单独的地址空间,进程中的变量是该进程的本地变量,不能从另一个进程访问。因此,为了同步多个进程,需要使用内核提供的信号量对象。例如,
sem_t *sem_open (const char *name, int oflag);
sem_open 系统调用返回一个指向信号量对象的指针,基于
name。希望同步的两个进程可以使用相同的
name通过内核访问信号量。 获取指向同一信号量的指针后,进程可以使用 sem_wait
和sem_post 系统调用进行同步。