无法从另一个进程 C++ 打开现有信号量

Can't open existing semaphore from another process C++

我正在尝试从另一个进程获取现有信号量。为了创建信号量,我使用了:

Semaphore(std::string name, int startState) {
    name = "Global\" + name;
    Sem = OpenSemaphore(SYNCHRONIZE | SEMAPHORE_MODIFY_STATE, true, (LPCWSTR)name.c_str());
    int s = (startState > 0);
    if (Sem == NULL) {
        Sem = CreateSemaphore(NULL, s, 1, (LPCWSTR)name.c_str());
    }
}

在第一个进程中正确创建了信号量。 GetLastError() returns 0。在第二个进程中,OpenSemaphore returns NULL。和 GetLastError() returns 2。 我试图仅通过“名称”获取信号量 - 没有“Global\”,但它得到了相同的结果。请帮忙)

如果您觉得需要使用 C 风格的转换(例如 (LPCWSTR)name.c_str()),您应该将其视为您做错事的标志。

就像你在这里所做的那样:std::string 是一个 narrow 字符(即 char)字符串,而您使用 wide 字符 (wchar_t) 函数。这意味着名称将不是您所期望的。

如果继续使用 std::string,则必须使用“ANSI”函数(例如 CreateSemaphoreA)。否则切换到使用宽字符的 std::wstring

解释了您看到的错误的原因(字符编码不匹配)。

我只想指出,在解决该问题后,您的代码中仍然存在竞争条件。

如果你想打开一个现有的信号量(或任何其他类型的命名内核对象),如果它不存在就创建它,那么不要浪费时间打开它,只需无条件地创建它,例如:

Semaphore(std::string name, int startState) {
    name = "Global\" + name;
    int s = (startState > 0);
    Sem = CreateSemaphoreA(NULL, s, 1, name.c_str());
}

如果对象已经存在,您将获得现有对象的句柄,输入参数将被忽略。否则,您将获得一个使用您的参数初始化的新对象的句柄。如果需要,GetLastError() 可用于告诉您对象是否已存在或重新创建。