在c ++中从另一个进程中解锁线程

Posted

技术标签:

【中文标题】在c ++中从另一个进程中解锁线程【英文标题】:Unlock a thread from another process, in c++ 【发布时间】:2009-08-05 08:56:41 【问题描述】:

我正在编写一个进程间通信模块(进程 A 和进程 B)。

B 中的通信线程是否可以在进程 A 完成特定操作后立即运行(解锁),我的意思是在 A 完成其操作后 B 不进行任何轮询或 B 等待太多?

管理这些问题的概念/模型/设计模式有哪些? (比进程间同步更精确的东西)。您推荐哪些库/方法?

谢谢。

编辑:我正在寻找适合三种主要操作系统的方法:Ms Windows、Apple Mac OS X、GNU/Linux。

【问题讨论】:

我误解了这个问题,认为这是一个线程间问题。我现在添加了有关如何在进程之间执行此操作的信息,希望对您有所帮助 【参考方案1】:

这是一项相当艰巨的工作:

对于 Unix 操作系统,您可以使用:

pthread 条件和带有 setpshared 参数的互斥锁。

注意:在Linux 2.6、Solaris下支持良好,但不支持FreeBSD和Cygwin(不知道Mac OS X)

对于 Unix,您也可以使用命名信号量,但我不知道它们的支持程度

对于 Windows,有一些事件...

这是一项艰巨的工作,尤其是对于 IPC...

因此,如果您想要可移植的东西,我建议您查看具有条件和互斥锁的 Boost.Interprocess...

但请确保您想要支持的所有操作系统都支持所有功能。

关于 Boost.Interprocess 的注意事项

仔细检查您需要使用的每个 Unix 操作系统的支持级别,因为 Boost.Interprosess 使用并不总是支持的 pthread_* 函数......然后失败返回到仿真——检查这种仿真的质量

另外,检查这些东西在 Windows 上是如何工作的——据我所知,Win32 API 中没有“共享内存”互斥锁,通常应该使用命名对象,所以检查支持什么以及如何支持。

【讨论】:

它只是错过了对 boost::interprocess::interprocess_semaphore 的额外提及【参考方案2】:

编辑:我误以为您需要线程间同步,已针对 IPC 进行了修订

我认为您需要诸如可等待事件之类的东西。

在 Windows 中,您可以使用 CreateEvent() 创建(或获取现有的)命名的自动重置事件。

当进程A完成处理时,它应该调用SetEvent(),而进程B应该调用WaitForSingleObject()休眠直到完成(或超时)。

或者,您可以使用由CreateSemaphore() 创建的信号量,初始化为0。 进程 A 通过调用 ReleaseSemaphore() 发出完成信号,而进程 B 再次使用 WaitForSingleObject() 等待完成。

在 Linux 和 OS X 下,您可以使用信号量达到类似的效果。 使用sem_open()创建一个命名信号量,初始值为0。

当进程 A 完成时,它应该调用 sem_post() 来增加信号量,而进程 B 应该调用 sem_wait() 休眠直到完成。

注意:信号量方法可能允许发出多个完成信号,您应该通过在 Windows 下设置最大计数来处理此问题,或者使用 sem_getvalue() 检查当前 sem 值是否正常


我认为条件变量符合您的要求,这是一个适用于 Linux 和 OSX 的示例

#include <pthread.h>
/* no error checking, quick and dirty sample */
pthread_mutex_t g_mutex;
pthread_cond_t g_cond;
int a_done = 0;

void init(void)

    pthread_mutex_init(&g_mutex, NULL);
    pthread_cond_init(&g_cond, NULL);


void thread_a(void *arg)

    /* do something here... */
    pthread_mutex_lock(&g_mutex);
    a_done = 1;
    pthread_cond_signal(&g_cond);
    pthread_mutex_unlock(&g_mutex);


void thread_b(void *arg)

    /* wait for a to complete */
    pthread_mutex_lock(&g_mutex);
    while (!a_done)
        pthread_cond_wait(&g_cond, &g_mutex);
    a_done = 0;
    pthread_mutex_unlock(&g_mutex);

在 Windows 下,您可以使用pthreads-win32,或在 Vista 下使用原生条件变量,请参阅MSDN Condition Variables 页面了解更多信息。

参考资料:

pthread_cond_wait pthread_cond_signal

【讨论】:

答案不处理进程间部分。 pthread-win32我没用过,检查兼容性问题 啊,我认为这是一个线程间问题。我稍后会修改答案【参考方案3】:

如果您的操作系统支持信号,您可以从信号处理程序解锁互斥锁,并在完成任务后立即从进程 A 发送信号。

进程 B 将等待互斥锁或其他同步工具,而 A 将处理任何东西,然后当完成发送信号 USR1 时,进程 B 中的 USR1 处理程序解锁相应的同步工具。

【讨论】:

好像是POSIX;你见过适应 Windows 的吗? 不确定您是否可以在 Windows 中正确使用信号,但我知道您还有其他选择,因为 windows 事件尚未使用它们。【参考方案4】:

最常见的是使用select()/poll()。如果有可用的输入,两者都可以检查多个文件描述符。两者都收到一个超时参数 - 这将防止忙碌等待,这可能会消耗 100% 的 CPU。这是非常适合中小型应用的解决方案。

另一种方法是在单独的线程中进行轮询。

如果您要开发大型应用程序,值得关注ACE framework 或 boost。这些框架是跨平台解决方案,经过精心设计和测试。

【讨论】:

感谢您的回答,但我的意思是“没有 B 进行任何轮询”。也许 select() 更合适? 我能做的唯一方法是发信号(Linux 中的 signal()),但根据我的经验,这种解决方案不适合高负载。在 Linux 上,信号也会中止系统调用(EINTR 错误),这会使您的程序不必要地复杂化。在超时为零的情况下调用 select()/poll(),只会检查是否有要读取的内容。之后,您可以继续执行其他任务。【参考方案5】:

嗯,根据我的观点和经验,以便携和简单的方式做到这一点的最佳方法是使用套接字。另外,您可以在不同的机器上拥有这两个进程(如果需要)。此外,您可以扩展通信以处理同步以外的更多问题。

如果您不想轮询,请使用在套接字上等待同步消息的线程。您以阻塞方式读取套接字。当您收到消息时,您使用标准的多线程同步来处理您的同步。在您的情况下,由于 B 应该等到 A 结束,您只需要在进程中以阻塞方式读取即可。

为了便于移植,请使用可移植的套接字库,例如 boost 或 ptypes 或其他。

【讨论】:

以上是关于在c ++中从另一个进程中解锁线程的主要内容,如果未能解决你的问题,请参考以下文章

线程模块threading

在后台线程中删除文件

Linux中从后台启动进程,应在命令结尾处加上啥符号

Perl ipc 使用管道从另一个进程启动一个进程的执行

在 c# 中从 W3wp 获取性能计数器

在 PCL 中从另一个点云中删除点?