等到另一个进程锁定然后解锁Win32互斥锁

时间:2014-11-26 19:21:19

标签: c++ c windows winapi ipc

我试图告诉生产者进程何时访问共享的窗口互斥锁。发生这种情况后,我需要锁定相同的互斥锁并处理相关数据。在Windows中是否有一种构建方式可以做到这一点,而不是一个荒谬的循环?

我知道通过在生产者流程中创建自定义Windows事件可以做到这一点,但我希望尽可能避免更改此程序代码。

我相信它会起作用(以一种非常低效的方式)就是这样(注意:这不是我真正的代码,我知道有10个不同的东西非常错误;我想避免做这样的事情) :

#include <Windows.h>

int main() {
    HANDLE h = CreateMutex(NULL, 0, "name");
    if(!h) return -1;

    int locked = 0;
    while(true) {
        if(locked) {
            //can assume it wont be locked longer than a second, but even if it does should work fine
            if(WaitForSingleObject(h, 1000) == WAIT_OBJECT_0) {
                // do processing...
                locked = 0;
                ReleaseMutex(h);
            }
        // oh god this is ugly, and wastes so much CPU...
        } else if(!(locked = WaitForSingleObject(h, 0) == WAIT_TIMEOUT)) {
            ReleaseMutex(h);
        }
    }
    return 0;
}

如果出于某种原因使用C ++有一种更简单的方法,我的代码就是这样。这个例子在C中更容易构建。

2 个答案:

答案 0 :(得分:2)

如果需要高效共享,您将无法避免更改制作人。你的设计从根本上来说是有缺陷的。

生产者需要能够在准备好消费数据时向消费者发出信号,并确保在忙碌消费时不会改变数据。单独使用一个互斥锁就无法做到这一点。

最好的方法是让生产者在数据准备就绪时设置一个事件,并让消费者在数据被消耗时重置事件。仅使用互斥锁 来同步对数据的访问,而不是表示数据准备就绪。

#include <Windows.h>

int main()
{
    HANDLE readyEvent = CreateEvent(NULL, TRUE, FALSE, "ready");
    if (!readyEvent) return -1;

    HANDLE mutex = CreateMutex(NULL, FALSE, "name");
    if (!mutex) return -1;

    while(true)
    {
        if (WaitForSingleObject(readyEvent, 1000) == WAIT_OBJECT_0)
        {
            if (WaitForSingleObject(mutex, 1000) == WAIT_OBJECT_0)
            {
                // process as needed...
                ResetEvent(readyEvent);
                ReleaseMutex(mutex);
            }
        }
    }

    return 0;
}

如果您无法更改生产者以使用事件,那么至少要为数据本身添加一个标志。生产者可以锁定互斥锁,更新数据和标记,以及解锁互斥锁。然后,消费者必须定期锁定互斥锁,检查标志并在设置标志时读取新数据,重置标志并解锁互斥锁。

#include <Windows.h>

int main()
{
    HANDLE mutex = CreateMutex(NULL, FALSE, "name");
    if (!mutex) return -1;

    while(true)
    {
        if (WaitForSingleObject(mutex, 1000) == WAIT_OBJECT_0)
        {
            if (ready)
            {
                // process as needed...
                ready = false;
            }
            ReleaseMutex(mutex);
        }
    }

    return 0;
}

无论哪种方式,你的逻辑都必须在生产者和消费者中进行调整。

否则,如果您根本无法更改生产者,那么您别无选择,只能单独更改消费者,只需检查数据的周期性变化:

#include <Windows.h>

int main()
{
    HANDLE mutex = CreateMutex(NULL, 0, "name");
    if (!mutex) return -1;

    while(true)
    {
        if (WaitForSingleObject(mutex, 1000) == WAIT_OBJECT_0)
        {
            // check data for changes
            // process new data as needed
            // cache results for next time...
            ReleaseMutex(mutex);
        }
    }

    return 0;
}

答案 1 :(得分:0)

棘手。我将回答基本问题:何时写入内存?

这可以通过四步解决方案来观察:

  1. 在观看过程中注入DLL
  2. STATUS_GUARD_PAGE_VIOLATION
  3. 添加向量异常处理程序
  4. 将保护页面位设置在2 MB内存范围内(发现它可能是一个挑战)
  5. 从向量异常处理程序,通知您的进程并重新建立保护位(它的一次性)
  6. 如果图像始终被完全重写,则可能只需要一个保护页面。