要从那次学习双进程守护提及,也算小半年之前的事情了。不懂互斥体、不懂事件、信号量等机制,你就说用互斥体、事件写双进程守护?
科普:
大学自学操做系统的时候不懂,慢慢的也就懂了。穿孔器、纸卡带的年代只有程序,为了解决人与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.并发