信号灯(用户模式 内核模式)

Posted 刘收获

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了信号灯(用户模式 内核模式)相关的知识,希望对你有一定的参考价值。

一.用户模式的信号灯

信号灯内部有个计数器,可以理解信号灯内部有N个灯泡,如果有一个灯泡亮着,就代表信号灯处于激发状态,如果全部熄灭,就代表信号灯处于未激发状态。

  创建信号灯:

  HANDLE CreateSemaphore(
      LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,// pointer to security attributes
      LONG lInitialCount,  // initial count
      LONG lMaximumCount,  // maximum count
      LPCTSTR lpName       // pointer to semaphore-object name
    );


  增加信号灯的计数器:
  BOOL ReleaseSemaphore(
    HANDLE hSemaphore,   // handle to the semaphore object
    LONG lReleaseCount,   // amount to add to current count
    LPLONG lpPreviousCount   // address of previous count
    );
 
  对信号灯执行一次等待操作,就会减少一个计数,就相当于熄灭一个灯泡。当计数为0时,也就是所有灯泡都熄灭时,当前线程进入睡眠状态,直到信号灯变成激发状态或者超时。

 

// Semaphore-ThreadSynchronization.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <windows.h>
void Sub_1();

HANDLE  __SemaphoreHandle = NULL;
int main()
{
	/*
	HANDLE  SemaphoreHandle = NULL;
	HANDLE  ThreadHandle = NULL;
	SemaphoreHandle = CreateSemaphore(NULL, 2, 2, NULL);   //创建两个亮着的灯泡
	WaitForSingleObject(SemaphoreHandle, INFINITE);        //熄灭一盏灯

	ReleaseSemaphore(
		SemaphoreHandle,   //信号量的句柄
		1,                 //增加个数
		NULL);            //用来传出先前的资源计数,设为NULL表示不需要传出
	
	WaitForSingleObject(SemaphoreHandle, INFINITE);  
	WaitForSingleObject(SemaphoreHandle, INFINITE);
	*/
	
	__SemaphoreHandle = CreateSemaphore(
		NULL,    //安全结构
		2,       //初始资源数量
		2,       //最大并发数量
		NULL);   //匿名信号量
		

	Sub_1();
	printf("Input AnyKey To Exit\r\n");
	getchar();
	return 0;
}


void Sub_1()
{
	WaitForSingleObject(__SemaphoreHandle, INFINITE); 
	printf("Sub_1()\r\n");
	Sub_1();
}

 

二.内核模式下的信号灯

  在内核模式下,信号灯对象用KSEMAPHORE数据结构表示。在使用信号灯对象钱,需要对其进行初始化(KeInitializeSemaphore

  KeReadStateSemaphore函数可以读取信号灯当前计数

  释放信号灯会增加信号灯计数,对应内核函数KeReleaseSemaphore函数。

 

#include "KSemaphore.h"


NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegisterPath)
{
	NTSTATUS Status = STATUS_SUCCESS;
	PDEVICE_OBJECT  DeviceObject = NULL;
	DriverObject->DriverUnload = DriverUnload;

	SeCreateSemaphore();
	return Status;
}


VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
	DbgPrint("DriverUnload()\r\n");
}
VOID SeCreateSemaphore()
{
	HANDLE ThreadHandle = NULL;
	KSEMAPHORE  Semaphore;
	ULONG  Count = 0;
	PVOID  ThreadObject = NULL;
	KeInitializeSemaphore(&Semaphore, 2, 2);
	Count = KeReadStateSemaphore(&Semaphore);
	DbgPrint("Semaphore Count:%d\r\n", Count);
	KeWaitForSingleObject(&Semaphore, Executive, KernelMode, FALSE, NULL);
	Count = KeReadStateSemaphore(&Semaphore);
	DbgPrint("Semaphore Count:%d\r\n", Count);
	KeWaitForSingleObject(&Semaphore, Executive, KernelMode, FALSE, NULL);
	PsCreateSystemThread(&ThreadHandle, 0, NULL, NULL, NULL, ThreadProcedure, &Semaphore);
	KeWaitForSingleObject(&Semaphore, Executive, KernelMode, FALSE, NULL);
	ObReferenceObjectByHandle(ThreadHandle, 0, NULL, KernelMode, &ThreadObject, NULL);
	KeWaitForSingleObject(ThreadObject, Executive, KernelMode, FALSE, NULL);
	ZwClose(ThreadHandle);
}


VOID ThreadProcedure(PVOID ParameterData)
{
	PKSEMAPHORE  Semaphore = (PKSEMAPHORE)ParameterData;
	KeReleaseSemaphore(Semaphore, IO_NO_INCREMENT, 1, FALSE);
	PsTerminateSystemThread(STATUS_SUCCESS);

}

  

以上是关于信号灯(用户模式 内核模式)的主要内容,如果未能解决你的问题,请参考以下文章

用于从 cloudkit 检索单列的代码模式/片段

Linux 磁盘分区

用户模式和内核模式:同时使用不同的程序

windows内核态调用readfile

Windows 驱动程序 - 来自用户模式的共享内存 -> 内核模式

进程切换一定有模式切换 ,反之不然