两个进程的 WinApi SpinLock 方法

WinApi SpinLock method for two Processes

我有一个关于 Win32 API 进程处理的问题。

我有两个进程。进程 1 在启动之前必须 运行 进程 2,它等待与进程 1 相同的资源。它是一个具有一些整数值的 .txt 文件。这意味着 Process1 应该首先启动,运行 Process2。 Process1 必须在 Process2 之后完成。 它应该按以下方式工作: 1.Process1被创建。 2.Process 1 被阻止。 3.Process 2 创建并执行。 4.Process 1 解锁并执行。 5.Process2结束。 6.Process 1 结束。

我在这里搜索了一个与我类似的问题,我只找到了下面的link,其中显示了SpinLock class:

C++11 Implementation of Spinlock using <atomic>

问题是正确实现它,我已经从 main() 函数中删除了 SpinLock 方法的错误实现。

几乎不可能找到任何在实践中使用这种方法的例子,因此我提出这个问题来看看:

#include <iostream>
#include <Windows.h>
#include <string>
#include <tchar.h>
#include <cstdlib>
#include <pthread.h>
#include <atomic>
using namespace std;

class SpinLock {
    atomic_flag locked = ATOMIC_FLAG_INIT ;
public:
    void lock() {
        while (locked.test_and_set(memory_order_acquire)) { ; }
    }
    void unlock() {
        locked.clear(memory_order_release);
    }
};

int main( int argc, TCHAR *argv[] )
{
    //process 1 generates N random values between 1 and 100,then saves it to txt file i argv[1] stores quanity of values, which will be saved to file
    STARTUPINFO si = {};
    si.cb = sizeof si;
    SpinLock SpinLockVar;
   PROCESS_INFORMATION pi = {};
   const TCHAR* target1 = _T("C:\USERS\Admin\Documents\File1.exe"); //process 1
   const TCHAR* target2 = _T("C:\USERS\Admin\Documents\File2.exe");
   //Process 1 , before starting generating values and saving them to file, runs Process2,which is awaiting for access to txt file (SPINLOCK ).
   //Process 1 is terminating after finishing Process 2

   if ( !CreateProcess(target1,GetCommandLine(), 0, FALSE, 0, 0, 0, 0, &si, &pi) )
    {
        cerr << "CreateProcess failed (" << GetLastError() << ").\n";
    }
    else
    {
        WaitForSingleObject(pi.hProcess, INFINITE);
        
        if ( PostThreadMessage(pi.dwThreadId, WM_QUIT, 0, 0) ) // Good
            cout << "Request to terminate process has been sent!";

        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    }
    if ( !CreateProcess(target2,0, 0, FALSE, 0, 0, 0, 0, &si, &pi) )
    {
        cerr << "CreateProcess failed (" << GetLastError() << ").\n";
    }
    else
    {
        WaitForSingleObject(pi.hProcess, INFINITE);
        /*
        if ( TerminateProcess(pi.hProcess, 0) ) // Evil
            cout << "Process terminated!";
        */
        if ( PostThreadMessage(pi.dwThreadId, WM_QUIT, 0, 0) ) // Good
            cout << "Request to terminate process has been sent!";

        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    }

    cin.sync();
    cin.ignore();
    
  

 
    return 0;
}

更新 我现在已经使用了互斥函数,它部分起作用了——它有一个互斥“自旋锁”机制,尽管它有时显示得很奇怪。我随机得到了我期望的结果,它是在我的程序 运行 之后随机生成的 - cmd 中的第一行来自 运行s process2 的线程,第二行是 process1[=17 的结果=]

请检查我的代码:

#include <windows.h>
#include <stdio.h>
#include <pthread.h>
#include <tchar.h>
#include <mutex>
#include <iostream>
HANDLE hMutex;

DWORD ThreadProc1(LPVOID* arg)  
{  
       
      const TCHAR* target = _T("C:\USERS\Admin\Documents\File2.exe");
    PROCESS_INFORMATION pInfo;
    STARTUPINFO sInfo = { sizeof(pInfo) };
    BOOL res = CreateProcess(target, 0, 0, FALSE, 0, 0, 0, 0, &sInfo, &pInfo); //process2
    if (!res) return 1;
      
      WaitForSingleObject(pInfo.hThread, INFINITE);
    CloseHandle(pInfo.hThread);
    CloseHandle(pInfo.hProcess);
      return TRUE;  
}  

 
int main(void)  
{  
     PROCESS_INFORMATION pInfo;
    STARTUPINFO sInfo = { sizeof(pInfo) };
    const TCHAR* target = _T("C:\USERS\Admin\Documents\File1.exe");
      HANDLE hThreads;  
      DWORD threadID1; 

      
      hMutex=CreateMutex(NULL, FALSE, NULL); //create mutex(resources=1)
      WaitForSingleObject(hMutex, INFINITE); //process2 call WaitForSingleObject(hmutex) first to get mutex
      hThreads=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, &hMutex, 0, &threadID1); 
      WaitForSingleObject(hMutex,INFINITE);//process1 call WaitForSingleObject(hmutex) and block
      BOOL res = CreateProcess(target, GetCommandLine(), 0, FALSE, 0, 0, 0, 0, &sInfo, &pInfo);//process1
      if (!res) return 1;
      ReleaseMutex(hMutex);// process2 do file operations, and then release mutex
      WaitForSingleObject(hMutex,INFINITE);// process1 WaitForSingleObject(hmutex) unblock(resources -1),
      ReleaseMutex(hMutex);  // then release mutex(resources +1) 

      
      CloseHandle(hMutex);   
      WaitForSingleObject(hThreads,INFINITE); 
      CloseHandle(hThreads);    //process 1 closing thread after process 2 ends
     CloseHandle(pInfo.hProcess);
     CloseHandle(pInfo.hThread);
      return 0;
}  

首先,我认为您不需要使用互斥锁或自旋锁。尽管第 4 步和第 5 步可能有所不同,但您可以使用 CREATE_SUSPENDED, create process2, wait for process2 to exit, then call ResumeThread(pi1.hThread) 创建 process1。

#include <windows.h>
#include <string>
#include <tchar.h>
#include <cstdlib>
#include <iostream>
using namespace std;
int main(int argc, TCHAR* argv[])
{

    STARTUPINFO si1 = { 0 }, si2 = { 0 };
    si1.cb = sizeof si1;
    si2.cb = sizeof si2;
    PROCESS_INFORMATION pi1 = { 0 }, pi2 = { 0 };

    const TCHAR* target1 = _T("C:\Users\drakew\source\repos\Project4\Debug\Project4.exe");
    const TCHAR* target2 = _T("C:\Users\drakew\source\repos\Project6\Debug\Project6.exe");


    if (!CreateProcess(target1, 0, 0, FALSE, 0, CREATE_SUSPENDED, 0, 0, &si1, &pi1))
    {
        cerr << "CreateProcess failed (" << GetLastError() << ").\n";
    }
    else
    {
        printf("Process1 is created ...\n");
        printf("Process1 is blocked ...\n");
        if (!CreateProcess(target2, 0, 0, FALSE, 0, 0, 0, 0, &si2, &pi2))//Process 2 is created and excecuted ...
        {
            cerr << "CreateProcess failed (" << GetLastError() << ").\n";
        }
        else
        {
            WaitForSingleObject(pi2.hProcess, INFINITE);
            printf("Process 2 ends ...\n");
            CloseHandle(pi2.hProcess);
            CloseHandle(pi2.hThread);
        }
        ResumeThread(pi1.hThread); //Process 1 is unlocked and executed ...
        WaitForSingleObject(pi1.hProcess, INFINITE);
        printf("Process 1 ends ...\n");
        CloseHandle(pi1.hProcess);
        CloseHandle(pi1.hThread);
    }
    cin.sync();
    cin.ignore();

    return 0;
}

那么,如果要阻塞在process1的具体位置,那么就得修改process1和process2保持同步。

我用事件实现锁

进程 1:

#include <Windows.h>
#include <iostream>
using namespace std;
int main()
{
    HANDLE hEvent1 = OpenEvent(EVENT_MODIFY_STATE| SYNCHRONIZE, FALSE, L"Global\MyEvent1");
    HANDLE hEvent2 = OpenEvent(EVENT_MODIFY_STATE| SYNCHRONIZE, FALSE, L"Global\MyEvent2");
    printf("process1: step1 ...\n");
    SetEvent(hEvent1);
    printf("process1: step2 ...\n");
    DWORD dwWaitResult = WaitForSingleObject(hEvent2, INFINITE);
    switch (dwWaitResult)
    {
    case WAIT_OBJECT_0:
        printf("process1: step4 ...\n");
        break;
    default:
        return FALSE;
    }
    CloseHandle(hEvent1);
    CloseHandle(hEvent2);
}

进程 2:

#include <Windows.h>
#include <iostream>
using namespace std;
int main()
{
    HANDLE hEvent1 = OpenEvent(EVENT_MODIFY_STATE | SYNCHRONIZE, FALSE, L"Global\MyEvent1");
    HANDLE hEvent2 = OpenEvent(EVENT_MODIFY_STATE | SYNCHRONIZE, FALSE, L"Global\MyEvent2");

    DWORD dwWaitResult = WaitForSingleObject(hEvent1, INFINITE);
    switch (dwWaitResult)
    {
    case WAIT_OBJECT_0:
        printf("process2: step3 ...\n");
        SetEvent(hEvent2);
        break;
    default:
        return FALSE;
    }
    CloseHandle(hEvent1);
    CloseHandle(hEvent2);
    return 1;
}

主要过程:

#include <windows.h>
#include <string>
#include <tchar.h>
#include <cstdlib>
#include <mutex>
#include <iostream>
using namespace std;
int main(int argc, TCHAR* argv[])
{

    STARTUPINFO si1 = { 0 }, si2 = { 0 };
    si1.cb = sizeof si1;
    si2.cb = sizeof si2;
    PROCESS_INFORMATION pi1 = { 0 }, pi2 = { 0 };
    mutex mtx;
    HANDLE hEvent1 = CreateEvent(NULL, FALSE, FALSE, L"Global\MyEvent1");
    HANDLE hEvent2 = CreateEvent(NULL, FALSE, FALSE, L"Global\MyEvent2");

    const TCHAR* target1 = _T("C:\path\process1.exe");
    const TCHAR* target2 = _T("C:\path\process2.exe");


    if (!CreateProcess(target1, 0, 0, FALSE, 0, 0, 0, 0, &si1, &pi1))
    {
        cerr << "CreateProcess failed (" << GetLastError() << ").\n";
    }
    else
    {
        if (!CreateProcess(target2, 0, 0, FALSE, 0, 0, 0, 0, &si2, &pi2))
        {
            cerr << "CreateProcess failed (" << GetLastError() << ").\n";
        }
        else
        {
            WaitForSingleObject(pi2.hProcess, INFINITE);
            printf("process2: step5 ...\n");
            CloseHandle(pi2.hProcess);
            CloseHandle(pi2.hThread);
        }

        WaitForSingleObject(pi1.hProcess, INFINITE);
        printf("process1: step6 ...\n");
        CloseHandle(pi1.hProcess);
        CloseHandle(pi1.hThread);
    }
    CloseHandle(hEvent1);
    CloseHandle(hEvent2);
    cin.sync();
    cin.ignore();
    return 0;
}

结果: