雙進程守護?內核對象?單實例....?抱歉會進程掛起...抱歉我還有HOOK....
要從那次學習雙進程守護說起,也算小半年以前的事情了。不懂互斥體、不懂事件、信號量等機制,你就說用互斥體、事件寫雙進程守護?
科普:
當年自學操作系統的時候不懂,慢慢的也就懂了。穿孔器、紙卡帶的年代只有程序,為了解決人與CPU的交互效率低下,單批道處理器當年就出現了。但是仍然滿足不了需求,這時候多批道處理也就成了時間產物(從晶體管到小規模集成電路到3D晶體管技術)。進程(PCB進程控制塊),也是為了解決多批道處理下程序不可控,結果不可復用(資源共享帶來的雙刃劍)問題才真正的被運用起來。然而分時系統、實時系統精準程度要求,高並發的需求等,線程也才真正的立足於系統,成為最小的調度執行單位。
原子操作:
簡單來說,保證利用某一資源時候,當前資源不被其他CPU搶占使用。
缺點:只能解決某一個變量,比如是一個變量數據做簡單運算(有相對的原子操作API)。
臨界區:
基於原子操作的缺點,臨界區概念慢慢形成。臨界區可以保護一段代碼指令。
由InitializeCriticalSection(..)初始化一個臨界區,誰初始化的這個臨界區就屬於誰,有擁有者的概念。擁有者無限調用EnterCriticalSection()則不會被阻塞,其他的則會被阻塞在外,直到DeleteCriricalSection()銷毀 ,臨界區由InitializeCriticalSection ------> LeaveCriticalSection形成了保護。
臨界區啥缺點?他不是內核對象?什麽是內核對象,我們可以把進程、線程、文件IO、互斥體、信號量、事件、線程池、訪問令牌、計時器等都叫做內核對象,可以參考《windows核心編程》一書。
既然是內核對象?當然可以跨進程、臨界區是無法做到這一點,互斥體也有類似於臨界區擁有則的概念,重要的是有兩種狀態:1、激發態 2、非激發態。來判斷當前互斥體是否被使用,而且如果互斥體內部進程或者線程崩潰,那麽互斥體空間將自動釋放且為激發態,但是他只能被擁者去則釋放,不可以被別的線程釋放。
創建一個互斥體CreateMutex(),一般互斥體用於寫單實例進程,因為互斥體(參數3)是系統全局唯一,可以判斷當前系統是否已存在該進程,如果存在則不再打開或則創建。
ReleaseMutex釋放存在的互斥體。
利用互斥體實現單一進程檢測源碼如下:
#include <stdio.h>
#include <iostream>
#include <Windows.h>
using std::cout;
using std::endl;
BOOL IsMutex()
{
HANDLE hMutex = NULL;
hMutex = CreateMutex(NULL, FALSE, L"TEXT");
if (hMutex)
{
if (ERROR_ALREADY_EXISTS == GetLastError())
{
ReleaseMutex(hMutex);
CloseHandle(hMutex);
return TRUE;
}
}
return FALSE;
}
int main(void)
{
if(IsMutex())
cout << "系統已存在TEXT互斥體" << endl;
else
cout << "第一次創建互斥體成功" << endl;
system("pause");
return 0;
}
信號量:
信號量當前信號數不為0,則代表為激發態。註意調用WaitForSingleObject()的時候,就會把信號數-1,也就是說如果信號數不為0,那麽使用該函數信號數-1,相當於又上了一把鎖,記得調用函數ReleaseSemaphore()恢復(信號數+1)。任何一個線程都可以進行釋放(互斥體成對出現),意味著多個線程可保護同一段代碼或者指令。
事件:
這是一個相對民主的內核對象,進程同步中用的也比較多。他可以設置等待函數對於此事件對象有沒有後遺癥。而且可以手動設置激發態或者非激發態,自主性非常強,很靈活。
1、CreateEventW()用來創建一個事件對象
2、OPenEventA()打開一個事件對象
3、SetEvent()設置為激發態
4、ReSetEvent()設置為非激發態
5、PulseEvent()手動設置激發態
6、CloseHandle()內核對象當引用計數為0,系統管理銷毀。
這些函數具體參數可以msdn查看或者百度看詳細信息,介紹那麽多下面也要貼上一段雙進程守護代碼。
雙進程守護程序一:
int main(void)
{
// 創建事件對象
HANDLE hEvent = CreateEvent(NULL, FALSE, TRUE, L"守護One.exe");
while (TRUE)
{
HANDLE hEventTow = OpenEvent(NULL, FALSE, L"守護Two.exe");
// 如果不存在則創建
if (!hEventTow)
{
CreateProcess(L"守護Two.exe", NULL, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &s_Si, &s_Pi);
WaitForSingleObject(s_Pi.hProcess, INFINITE);
CloseHandle(s_Pi.hThread);
CloseHandle(s_Pi.hProcess);
}
else
CloseHandle(hEventTow);
}
system("pause");
return 0;
}
雙進程守護程序二:
STARTUPINFO s_Si = {};
PROCESS_INFORMATION s_Pi = {};
// 創建事件對象
HANDLE hEvent = CreateEvent(NULL, FALSE, TRUE, L"守護Two.exe");
while (TRUE)
{
HANDLE hEventTow = OpenEvent(NULL, FALSE, L"守護One.exe");
// 如果不存在則創建
if (!hEventTow)
{
CreateProcess(L"守護One.exe", NULL, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &s_Si, &s_Pi);
WaitForSingleObject(s_Pi.hProcess, INFINITE);
CloseHandle(s_Pi.hThread);
CloseHandle(s_Pi.hProcess);
}
else
CloseHandle(hEventTow);
}
system("pause");
return 0;
雙進程守護缺點很多,假如我掛起其中一個進程(不被響應),另一個進程則可關閉。
我們還有HOOK來保護自己,下次用一個簡單的mfc來聊一聊,fs寄存器_kpcr,還有一些Hook.
雙進程守護?內核對象?單實例....?抱歉會進程掛起...抱歉我還有HOOK....