如何同步两个进程?

时间:2008-10-30 00:29:47

标签: synchronization hardware process pthreads named-pipes

我想在同一工作站上的两个应用程序(进程)中使用一个HW接口。 HW需要单个初始化调用,然后应用程序使用相同的函数(在同一个库中)与HW进行许多事务。

所以每个应用都应该这样:

main()
    // I don't know if another app already init'ed the HW
    ret = hw_init_lock(non-blocking)

    if ret = OK
        // no one else has done this, I have to
        init_hw()
    else
       //someone else has already init'ed the HW, I gotta make sure it stays that way
       //as long as I'm alive
       increment_hw_init_ref_counter()

    hw_trans_lock(blocking)
    hw_trans()
    hw_trans_unlock()
    ....

    //exit app, uninit hw if we are last out
    ret = decrement_hw_init_ref_counter()
    if ret == 0
        uninit_hw()

    exit(0)

我可以在两个应用程序之间共享的锁定和引用计数调用中使用什么机制?我在想命名管道,即mkfifo()。

6 个答案:

答案 0 :(得分:9)

POSIX semaphore是要走的路。由于您希望跨进程共享相同的信号量,因此需要使用命名信号量。:

  

命名信号量由a标识   表格名称/某些名称。二   流程可以在同一个上运行   通过传递相同的命名信号量   名称为sem_open(3)。

答案 1 :(得分:4)

信号量和互斥量/条件变量是良好的,非常高性能的原语,适用于线程之间或进程之间。

所有这些都是基于对共享内存执行的测试和设置或其他原子操作的想法(通常是在现实中)。

如果您希望通过网络分发流程,那么信号量和互斥量可能不适合您 - 它们只能在一台计算机上运行。管道和套接字更通常是网络可扩展的。

互斥体,条件变量和信号量的简短摘要:

<强>互斥

互斥锁是一个可以锁定或解锁的基元。锁定它的进程/线程必须是解锁它的进程/线程。此所有权方面允许操作系统应用一些有趣的优化,例如优先级继承和优先级上限协议(以避免优先级倒置)。 但是,互斥锁没有与之关联的计数。一般来说,你不能锁定已经锁定的互斥锁,并保留它被“锁定两次”的内存(我认为有一些允许这样做的扩展,但它们并不是随处可用)

条件变量

互斥锁非常适合......嗯,MUTual EXclusion。但是,如果您需要阻止与您相互排斥的对象相关联的条件,该怎么办?为此,您使用条件变量或CV。 CV与互斥锁相关联。例如,假设我有一个输入数据队列,我的进程想要访问这些数据。一个人抓住互斥锁,这样它就可以看到队列而不用担心干扰。但是,它发现队列为空,并且想要等待队列中的某些内容。因此它等待“队列非空”条件变量。这里有趣的部分是,因为CV与互斥锁相关联,所以一旦发出条件变量信号,互斥锁就会自动重新获取。因此,一旦在等待CV之后进程唤醒,它就知道它再次拥有对队列的独占访问权。它所做的知道的是队列中是否真的有任何东西 - 也许两个进程在CV上等待 - 有一件事情进来了 - 并且第一优先进入并将“事物”排队在第二件事醒来之前。因此,无论何时使用CV,您都需要RECHECK条件,如下所示:

mutex_enter(m);
while (! condition) {
   cond_wait(m, c); // drop mutex lock;  wait on cv;  reacquire mutex
}
//processing related to condition
mutex_exit(m);

<强>信号灯

好的,那就是互斥和条件变量。信号量更简单。它们可以通过任何进程递增和递减。他们有记忆 - 他们会计算 - 所以你可以用它们来确定有多少病情已经发生。条件变量不是这样。此外,由于信号量可以通过一个进程递减并递增另一个进程,因此它们没有所有权方面 - 因此没有优先级继承,也没有优先级反转避免。

现在,最后 - 所有这些机制都需要共享内存才能实现高效。这对您来说可能没问题,但请注意 - 如果您认为您的申请最终可能会被分发,那么互斥,条件变量和信号量可能不适合您。管道和套接字虽然开销高得多,但可以相当直接地在网络上扩展。

答案 2 :(得分:2)

使用POSIX semaphores

答案 3 :(得分:2)

由于您只需要一个信号量为1,因此互斥量就足够了。

答案 4 :(得分:1)

我认为

  

......两个应用程序之间共享?

意味着您希望这两件事作为单独的流程运行?如果这不是真的,并且它们作为单个进程运行(具有多个线程),那么信号量和互斥量的建议是最佳选择,应该非常简单。

请注意,答案取决于您访问此硬件的确切方式。例如,如果它通过文件公开,则可以使用正常的文件锁定。

但是,如果您尝试在两个进程之间同步对硬件的访问,则这是另一回事。 我想首先要说的是,如果可以的话,更容易同步一个进程来负责访问硬件。在此模型中,您可能有一个充当硬件服务器的进程 - 接受来自其他进程的请求并代表他们执行读写操作。 几乎任何形式的进程间通信都是合适的,但为了简单起见,诸如消息队列(link)之类的东西可能适合某些适当的数据结构(例如,一个标志来指示它是读操作还是写操作,偏移从硬件的基地址,字节数,缓冲区(在写入的情况下))

如果将所有直接硬件访问放入单个进程中是不合适的,那么您将必须使用适当的同步方案。 我会调查文件锁的使用(并实现一个基本的互斥方案),或使用命名的信号量(如albertb建议的那样)

答案 5 :(得分:1)

我认为如果我们想要同步多个正在运行的进程,那么我们可以使用一种称为文件锁的非常简单的技术。

有关详细信息,请参阅此文章: http://blog.markedup.com/2014/07/easy-mode-synchronizing-multiple-processes-with-file-locks/