7

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

所以每个应用程序都应该像这样:

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()。

4

6 回答 6

9

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

命名信号量由 /somename 形式的名称标识。通过将相同的名称传递给 sem_open(3),两个进程可以对同一个命名的信号量进行操作。

于 2008-10-30T02:02:13.073 回答
4

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

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

如果您希望通过网络分发您的进程,那么信号量和互斥锁可能不适合您——它们只在一台机器上工作。管道和套接字通常是网络可扩展的。

互斥量、条件变量和信号量的简要总结:

互斥体

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

条件变量

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

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

信号量

好的,那就是互斥锁和条件变量。信号量更简单。它们可以通过任何进程递增和递减。它们有记忆——它们会计数——因此您可以使用它们来确定发生了多少情况。条件变量并非如此。此外,因为信号量可以由一个进程递减并由另一个进程递增,所以它们没有所有权方面——因此没有优先级继承,也没有优先级反转避免是可能的。

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

于 2008-10-30T06:09:24.023 回答
2

使用POSIX 信号量

于 2008-10-30T00:39:57.280 回答
2

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

于 2008-10-30T01:14:39.470 回答
2

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

更多详情请参考这篇文章:http: //blog.markedup.com/2014/07/easy-mode-synchronizing-multiple-processes-with-file-locks/

于 2015-03-25T19:48:47.843 回答
1

我假设

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

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

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

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

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

于 2008-10-30T02:05:43.457 回答