Warm tip: This article is reproduced from serverfault.com, please click

c++-ReleaseMutex在错误的时间和程序不同步winapi

(c++ - ReleaseMutex at the wrong time and the programs don't synchronize winapi)

发布于 2020-11-30 17:17:28

我整天都在c ++程序上工作,我找不到丢失的内容。问题是我尝试使用winapi与Mutex同步2个程序。我需要使用winapi文件映射将随机的内容从program1发送到program2,但是每次运行它时,program1都会在文件映射中写入所有内容,并且在运行每个实例之后,program2只读取文件映射中写入的最后一个数字。这两个之间没有同步。

我需要使用第一个程序中的CreateProcess函数打开第二个cpp程序。我认为我没有在正确的时间释放互斥锁,或者我没有在正确的时间启动第二个cpp文件,但是我尝试的所有方法均无效。

这是代码:

程序1:

#include <iostream>
#include <Windows.h>
#include <time.h>
using namespace std;

struct RandomSum {
   DWORD a;
   DWORD b;
};


int main()
{
   //srand((unsigned int)time(NULL));
   cout << "inside process 1" << endl;

   HANDLE common_mutex = CreateMutex(
       NULL,              // default security attributes
       TRUE,             // initially not owned
       "mainMutex");             // unnamed mutex


   HANDLE create_file_mapping_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 
  0, 1024 * 1024, "data");
   if (create_file_mapping_handle == NULL) {
       printf("Cannot create file mapping. Error code: %d", GetLastError());
       return 0;
   }

   unsigned char* pData = (unsigned char*)MapViewOfFile(create_file_mapping_handle, 
   FILE_MAP_ALL_ACCESS, 0, 0, 0);
   if (pData == NULL) {
       printf("Cannot get pointer to file mapping. Error code: %d", GetLastError());
       CloseHandle(create_file_mapping_handle);
       return 0;
   }



   //create new process
   PROCESS_INFORMATION process2;
   STARTUPINFO si;
   memset(&si, 0, sizeof(si));
   si.cb = sizeof(si);
   if (!CreateProcess("C:\\Users\\raztu\\Desktop\\tema5to6CSSO\\process1\\Debug\\process2.exe", NULL, 
NULL, NULL, FALSE, 0, NULL, NULL, &si, &process2)) {
       printf("Cannot create process.\n");
       return 0;
   }


   for (int i = 0; i < 50; ++i) {

   }

   int counter = 0;
   while (counter < 100) {
       DWORD dwWaitResult = WaitForSingleObject(
           common_mutex,    // handle to mutex
           INFINITE);  // no time-out interval

       if (dwWaitResult == WAIT_OBJECT_0) {
           cout << "am intrat in sender process si scriu in file mapping" << endl;
           RandomSum test;

           DWORD randomNumber = rand() % 50;
           test.a = randomNumber;
           test.b = 2 * test.a;
           memcpy(pData, &test, sizeof(RandomSum));
           cout << "in process 1: " << "a = " << test.a << " b= " << test.b << endl;
        
       }
       ReleaseMutex(common_mutex);
       cout << "last cout" << endl;
       ++counter;
   }

   CloseHandle(create_file_mapping_handle);
   CloseHandle(common_mutex);
   //getchar();
   return 0;
}

程序2:

#include <iostream>
#include <Windows.h>
#include <time.h>
using namespace std;

struct RandomSum {
   DWORD a;
   DWORD b;
};

int main()
{
   cout << "inside process2" << endl;
   //srand((unsigned int)time(NULL));



cout << "something new in process2" << endl;


LPCWSTR data = L"data";
HANDLE hData = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "data");

unsigned char* pData = (unsigned char*)MapViewOfFile(hData, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (pData == NULL) {
    printf("Cannot get pointer to file mapping. Error code: %d", GetLastError());
    CloseHandle(hData);
    return 0;
}

HANDLE common_mutex = OpenMutex(
    SYNCHRONIZE,
    FALSE,
    "mainMutex"
);

int counter = 0;
while (counter < 100) {
    DWORD dwWaitResult = WaitForSingleObject(
        common_mutex,    // handle to mutex
        INFINITE);  // no time-out interval

    if (dwWaitResult == WAIT_OBJECT_0) {
        cout << "a inceput procesul 2" << endl;
        RandomSum test;

        memcpy(&test, pData, sizeof(RandomSum));

        cout << "a is" << test.a << " and b is " << test.b << endl;
        
    }
    ReleaseMutex(common_mutex);
    ++counter;
   
}



CloseHandle(hData);
CloseHandle(common_mutex);
//getchar();
}

你能告诉我怎么了吗?

Questioner
JohnMat
Viewed
0
Drake Wu 2020-12-01 11:15:37

你不能使用互斥锁来同步这两个过程。由program1释放的互斥锁可以再次由program1捕获。

每次我运行它时,program1都会写入文件映射中的所有内容,并且在运行每个实例之后,program2仅读取文件映射中写入的最后一个数字。

可能是program1发行版的互斥锁始终由program1本身捕获(100次),然后由program2捕获。一个进程需要通知另一进程它已经完成了读写(使用IPC)。你可以创建2个事件,然后使用它来通知每个进程中的另一个进程。

程序1:

#include <iostream>
#include <Windows.h>
#include <time.h>
using namespace std;

struct RandomSum {
    DWORD a;
    DWORD b;
};


int main()
{
    //srand((unsigned int)time(NULL));
    cout << "inside process 1" << endl;

    HANDLE hEvent1 = CreateEvent(NULL, FALSE, TRUE, "MyEvent1");
    HANDLE hEvent2 = CreateEvent(NULL, FALSE, FALSE, "MyEvent2");

    HANDLE create_file_mapping_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
        0, 1024 * 1024, "data");
    if (create_file_mapping_handle == NULL) {
        printf("Cannot create file mapping. Error code: %d", GetLastError());
        return 0;
    }

    unsigned char* pData = (unsigned char*)MapViewOfFile(create_file_mapping_handle,
        FILE_MAP_ALL_ACCESS, 0, 0, 0);
    if (pData == NULL) {
        printf("Cannot get pointer to file mapping. Error code: %d", GetLastError());
        CloseHandle(create_file_mapping_handle);
        return 0;
    }

    //create new process
    PROCESS_INFORMATION process2;
    STARTUPINFO si;
    memset(&si, 0, sizeof(si));
    si.cb = sizeof(si);
    if (!CreateProcess("C:\\path\\program2.exe", NULL,
        NULL, NULL, FALSE, 0, NULL, NULL, &si, &process2)) {
        printf("Cannot create process.\n");
        return 0;
    }
    CloseHandle(process2.hThread);
    CloseHandle(process2.hProcess);    
    int counter = 0;
    while (counter < 100) {
        DWORD dwWaitResult = WaitForSingleObject(
            hEvent1,    // handle to mutex
            INFINITE);  // no time-out interval

        if (dwWaitResult == WAIT_OBJECT_0) {
            cout << "am intrat in sender process si scriu in file mapping" << endl;
            RandomSum test;

            DWORD randomNumber = rand() % 50;
            test.a = randomNumber;
            test.b = 2 * test.a;
            memcpy(pData, &test, sizeof(RandomSum));
            cout << "in process 1: " << "a = " << test.a << " b= " << test.b << endl;
            cout << "last cout" << endl;
            SetEvent(hEvent2);
        }

        ++counter;
    }
    UnmapViewOfFile(pData);
    CloseHandle(create_file_mapping_handle);
    CloseHandle(hEvent1);
    CloseHandle(hEvent2);
    //getchar();
    return 0;
}

程序2:

#include <iostream>
#include <Windows.h>
#include <time.h>
using namespace std;

struct RandomSum {
    DWORD a;
    DWORD b;
};

int main()
{
    cout << "inside process2" << endl;
    //srand((unsigned int)time(NULL));

    cout << "something new in process2" << endl;
    HANDLE hEvent1 = OpenEvent(EVENT_MODIFY_STATE | SYNCHRONIZE, FALSE, "MyEvent1");
    HANDLE hEvent2 = OpenEvent(EVENT_MODIFY_STATE | SYNCHRONIZE, FALSE, "MyEvent2");

    LPCWSTR data = L"data";
    HANDLE hData = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "data");

    unsigned char* pData = (unsigned char*)MapViewOfFile(hData, FILE_MAP_ALL_ACCESS, 0, 0, 0);
    if (pData == NULL) {
        printf("Cannot get pointer to file mapping. Error code: %d", GetLastError());
        CloseHandle(hData);
        return 0;
    }

    int counter = 0;
    while (counter < 100) {
        DWORD dwWaitResult = WaitForSingleObject(
            hEvent2,    // handle to mutex
            INFINITE);  // no time-out interval
        if (dwWaitResult == WAIT_OBJECT_0) {
            cout << "a inceput procesul 2" << endl;
            RandomSum test;

            memcpy(&test, pData, sizeof(RandomSum));

            cout << "a is " << test.a << " and b is " << test.b << endl;
            SetEvent(hEvent1);
        }
        ++counter;

    }
    UnmapViewOfFile(pData);
    CloseHandle(hData);
    CloseHandle(hEvent1);
    CloseHandle(hEvent2);
    //getchar();
}

或者直接使用你用于同步的共享内存。使用的第一个字节pdata作为信号位,每个进程监视是否轮到该执行。

程序1:

#include <iostream>
#include <Windows.h>
#include <time.h>
using namespace std;

struct RandomSum {
    DWORD a;
    DWORD b;
};
BOOL WaitForProcess2(unsigned char* shared_address)
{
    while (*shared_address != 1);//wait until the process1 set the first byte to 1;
    return true;
}

int main()
{
    //srand((unsigned int)time(NULL));
    cout << "inside process 1" << endl;


    HANDLE create_file_mapping_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
        0, 1024 * 1024, "data");
    if (create_file_mapping_handle == NULL) {
        printf("Cannot create file mapping. Error code: %d", GetLastError());
        return 0;
    }

    unsigned char* pData = (unsigned char*)MapViewOfFile(create_file_mapping_handle,
        FILE_MAP_ALL_ACCESS, 0, 0, 0);
    if (pData == NULL) {
        printf("Cannot get pointer to file mapping. Error code: %d", GetLastError());
        CloseHandle(create_file_mapping_handle);
        return 0;
    }
    *pData = 1;
    //create new process
    PROCESS_INFORMATION process2;
    STARTUPINFO si;
    memset(&si, 0, sizeof(si));
    si.cb = sizeof(si);
    if (!CreateProcess("C:\\path\\program2.exe", NULL,
        NULL, NULL, FALSE, 0, NULL, NULL, &si, &process2)) {
        printf("Cannot create process.\n");
        return 0;
    }
    CloseHandle(process2.hThread);
    CloseHandle(process2.hProcess);
    int counter = 0;
    while (counter < 100) {
        if (WaitForProcess2(pData)) {
            cout << "am intrat in sender process si scriu in file mapping" << endl;
            RandomSum test;

            DWORD randomNumber = rand() % 50;
            test.a = randomNumber;
            test.b = 2 * test.a;
            memcpy(pData+1, &test, sizeof(RandomSum)); //"pData + 1" skip the first signal bit
            cout << "in process 1: " << "a = " << test.a << " b= " << test.b << endl;
            cout << "last cout" << endl;
            *pData = 2;
        }
        ++counter;
    }
    UnmapViewOfFile(pData);
    CloseHandle(create_file_mapping_handle);
    //getchar();
    return 0;
}

程序2:

#include <iostream>
#include <Windows.h>
#include <time.h>
using namespace std;

struct RandomSum {
    DWORD a;
    DWORD b;
};
BOOL WaitForProcess1(unsigned char* shared_address)
{
    while (*shared_address != 2); //wait until the process1 set the first byte to 2;
    return true;
}
int main()
{
    cout << "inside process2" << endl;
    //srand((unsigned int)time(NULL));

    cout << "something new in process2" << endl;

    LPCWSTR data = L"data";
    HANDLE hData = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "data");

    unsigned char* pData = (unsigned char*)MapViewOfFile(hData, FILE_MAP_ALL_ACCESS, 0, 0, 0);
    if (pData == NULL) {
        printf("Cannot get pointer to file mapping. Error code: %d", GetLastError());
        CloseHandle(hData);
        return 0;
    }

    int counter = 0;
    while (counter < 100) {

        if (WaitForProcess1(pData)) {
            cout << "a inceput procesul 2" << endl;
            RandomSum test;

            memcpy(&test, pData + 1, sizeof(RandomSum)); //"pData + 1" skip the first signal bit

            cout << "a is " << test.a << " and b is " << test.b << endl;
            *pData = 1;
        }
        ++counter;

    }
    UnmapViewOfFile(pData);
    CloseHandle(hData);

    //getchar();
}