要從那次學習雙進程守護提及,也算小半年之前的事情了。不懂互斥體、不懂事件、信號量等機制,你就說用互斥體、事件寫雙進程守護?
科普:
大學自學操做系統的時候不懂,慢慢的也就懂了。穿孔器、紙卡帶的年代只有程序,爲了解決人與CPU的交互效率低下,單批道處理器當年就出現了。可是仍然知足不了需求,這時候多批道處理也就成了時間產物(從晶體管到小規模集成電路到3D晶體管技術)。進程(PCB進程控制塊),也是爲了解決多批道處理下程序不可控,結果不可複用(資源共享帶來的雙刃劍)問題才真正的被運用起來。然而分時系統、實時系統精準程度要求,高併發的需求等,線程也才真正的立足於系統,成爲最小的調度執行單位。
而原子操做、臨界區、互斥體這些東西都要基於多線程來講,線程同步、異步同步。也就有了消費者與生產者,哲學家等同步問題。簡單理解爲保證數據不混亂、有層次有邏輯的去相互配合執行任務。有緊急任務(高優先級)能夠搶佔處理機,並且具備公平性,每一個進程都有機會被運行;有較大的吞吐量,全部要有合理的調度算法。ios
原子操做:
簡單來講,保證利用某一資源時候,當前資源不被其餘CPU搶佔使用。
缺點:只能解決某一個變量,好比是一個變量數據作簡單運算(有相對的原子操做API)。
臨界區:
基於原子操做的缺點,臨界區概念慢慢造成。臨界區能夠保護一段代碼指令。
由InitializeCriticalSection(..)初始化一個臨界區,誰初始化的這個臨界區就屬於誰,有擁有者的概念。
擁有者無限調用EnterCriticalSection()則不會被阻塞,其餘的則會被阻塞在外,直到DeleteCriricalSection()銷燬 ,臨界區由InitializeCriticalSection ------> LeaveCriticalSection造成了保護。
互斥體:
臨界區啥缺點?他不是內核對象?什麼是內核對象,咱們能夠把進程、線程、文件IO、互斥體、信號量、事件、線程池、訪問令牌、計時器等都叫作內核對象,能夠參考《windows核心編程》一書。
既然是內核對象?固然能夠跨進程、臨界區是沒法作到這一點,互斥體也有相似於臨界區擁有則的概念,重要的是有兩種狀態:一、激發態 二、非激發態。來判斷當前互斥體是否被使用,並且若是互斥體內部進程或者線程崩潰,那麼互斥體空間將自動釋放且爲激發態,可是他只能被擁者去則釋放,不能夠被別的線程釋放。
建立一個互斥體CreateMutex(),通常互斥體用於寫單實例進程,由於互斥體(參數3)是系統全局惟一,能夠判斷當前系統是否已存在該進程,若是存在則再也不打開或則建立。
OpenMutexW()打開一個互斥體
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)。任何一個線程均可以進行釋放(互斥體成對出現),意味着多個線程可保護同一段代碼或者指令。
事件:
這是一個相對民主的內核對象,進程同步中用的也比較多。他能夠設置等待函數對於此事件對象有沒有後遺症。並且能夠手動設置激發態或者非激發態,自主性很是強,很靈活。
一、CreateEventW()用來建立一個事件對象
二、OPenEventA()打開一個事件對象
三、SetEvent()設置爲激發態
四、ReSetEvent()設置爲非激發態
五、PulseEvent()手動設置激發態
六、CloseHandle()內核對象當引用計數爲0,系統管理銷燬。
這些函數具體參數能夠msdn查看或者百度看詳細信息,介紹那麼多下面也要貼上一段雙進程守護代碼。
雙進程守護程序一:windows
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.
併發