两个进程的 WinApi SpinLock 方法
Posted
技术标签:
【中文标题】两个进程的 WinApi SpinLock 方法【英文标题】:WinApi SpinLock method for two Processes 【发布时间】:2020-11-27 00:55:17 【问题描述】:我有一个关于 Win32 API 进程处理的问题。
我有两个进程。进程 1 在启动之前必须运行进程 2,它等待与进程 1 相同的资源。它是一个带有一些整数值的.txt
文件。这意味着应该首先启动 Process1 并运行 Process2。 Process1 必须在 Process2 之后完成。
它应该如下工作:
1.Process1 被创建。
2.进程1被阻塞。
3.Process 2被创建并执行。
4.进程1被解锁并执行。
5.流程2结束。
6.流程1结束。
我在这里搜索了一个与我类似的问题,我只找到了下面的链接,其中显示了 SpinLock
类:
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 中的第一行来自运行 process2 的线程,第二行是 process1 的结果
请检查我的代码:
#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;
【问题讨论】:
需要命名互斥体,使其在进程边界之外可见。使用 CreateMutex()。 仅供参考,向pi.dwThreadId
发布WM_QUIT
消息是没有用的,因为拥有该线程的进程(由pi.hProcess
表示)在WaitForSingleObject(pi.hProcess, INFINITE)
退出时已经完全终止。等待进程HANDLE
的全部意义在于检测进程何时终止。
您提到process2必须在process1之前运行,但是您的代码显示您先运行process1,然后退出并运行process2。你能简单地改变顺序来解决问题而不使用自旋锁吗?因为这两个进程没有同时运行。
或者你想使用CreateFile
的dwShareMode
参数(在2个进程中)来限制其他进程的访问。
实际上我删除了我对这些进程所做的所有更改,因为它们不正确,这就是为什么我有像 Process1,Process2 这样的命令 - 关键是,Process1 在开始之前必须执行 Process 2。我目前正在尝试Create Mutex
..
【参考方案1】:
首先,我认为您不需要使用互斥锁或自旋锁。您可以使用CREATE_SUSPENDED
创建 process1,创建 process2,等待 process2 退出,然后调用 ResumeThread(pi1.hThread)
,尽管第 4 步和第 5 步可能存在差异。
#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;
结果:
【讨论】:
谢谢,我会试试的,虽然我设法在上面添加了 Mutex - update ;) 我用了你回复的第一个代码,稍微修改了一下,问题就解决了:)以上是关于两个进程的 WinApi SpinLock 方法的主要内容,如果未能解决你的问题,请参考以下文章