两个进程的 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;
}
结果:
我有一个关于 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;
}
结果: