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

一.用户模式的信号灯

信号灯内部有个计数器,可以理解信号灯内部有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);

}

  

时间: 2024-08-04 11:58:04

信号灯(用户模式 内核模式)的相关文章

Windows 用户和内核模式

上图: APP -> user mode OS-> kernel mode Drivers -> user or kernel mode 正所谓 一阴一阳之谓道,继之者善也,成之者性也.仁者见之谓之仁,知者见之谓之知.百姓日用而不知,故君子之道鲜矣

理解Windows内核模式与用户模式

 1.基础 运行 Windows 的计算机中的处理器有两个不同模式:"用户模式"和"内核模式".根据处理器上运行的代码的类型,处理器在两个模式之间切换.应用程序在用户模式下运行,核心操作系统组件在内核模式下运行.多个驱动程序在内核模式下运行,但某些驱动程序在用户模式下运行. 当启动用户模式的应用程序时,Windows 会为该应用程序创建"进程".进程为应用程序提供专用的"虚拟地址空间"和专用的"句柄表格"

用户模式和内核模式

https://msdn.microsoft.com/zh-cn/library/windows/hardware/ff554836 运行 Windows 的计算机中的处理器有两个不同模式:"用户模式"和"内核模式".根据处理器上运行的代码的类型,处理器在两个模式之间切换.应用程序在用户模式下运行,核心操作系统组件在内核模式下运行.多个驱动程序在内核模式下运行,但某些驱动程序在用户模式下运行. 当启动用户模式的应用程序时,Windows 会为该应用程序创建"

内存管理:用户模式和内核模式

进程 一个具有一定独立功能的程序在一组数据集合上的一次动态执行过程. 进程最显著的特点是拥有独立的地址空间. 内核模式 内核空间存放的是操作系统内核代码和数据,是被所以程序共享的. 操作系统禁止用户进程直接访问内核空间. 用户进程调用系统调用(System Call)来访问内核空间. 用户模式 用户空间存放的是应用进程的代码和数据,是进程私有的,其他进程一般无法访问. 为什么要区分两种模式? 内核 管理硬件 提供接口,供上层程序使用 为什么内核和用户进程要共用地址空间? 内核拥有独立的地址空间,

浅析Windows系统调用——2种切换到内核模式的方法

首先总结2种切换到内核模式方法的各自流程: 内存法(中断法): (用户模式)WriteFile() -> ntdll!NtWriteFile() -> ntdll!KiIntSystemCall() -> int 2Eh -> 查找IDT的内存地址,偏移0x2E处 ->(内核模式)nt!KiSystemService() -> nt!KiFastCallEntry() -> nt!NtWriteFile() 通过0x2E中断转移控制到内核模式后,系统服务分发/调度

Windows核心编程笔记(7)----内核模式下的线程同步

1.内核对象同步与用户模式下同步对比 使用内核对象的唯一缺点就是性能,调用内核对象函数时,调用线程必须从用户模式切换到内核模式,这种切换是相当 耗时的. 内核对象(进程.线程.作业)要么处于触发态,要么处于未触发状态.进程内核对象在创建时总是处于未触发状态, 当进程终止时,操作系统会自动使进程内核对象变成触发状态.当进程内核对象处于触发状态后,将永远保持这种状态, 再也不能变回未触发状态. 2.等待内核对象 WaitForSingleObject等待单个内核对象,WaitForMultipleO

WIN7-X64内核模式下编程实现导出表列表查看

内核模式下查看导出表需要注意的事项比在用户模式下要考虑更加周详: X64环境倒不是变化太多,指针定是64位的,数据数据及指针指向的数据类型需要注意: 不费话,直接上源码,VS2010+WDK7600下编译通过: /// /// @file aux_list.c /// @author cntom90151 /// @date2015-09-24 /// #include <ntddk.h> #include <WinDef.h> #include <aux_klib.h>

使用WinDbg调试入门(内核模式)

windbg是一个内核模式和用户模式调试器,包含在Windows调试工具中.这里我们提供了一些实践练习,可以帮助您开始使用windbg作为内核模式调试器. 设置内核模式调试 内核模式调试环境通常有两台计算机:主机和目标计算机.调试器在主机上运行,正在调试的代码在目标计算机上运行.主机和目标通过调试电缆连接.Windows调试程序支持以下类型的电缆进行调试: Ethernet USB 2.0 USB 3.0 1394 Serial (also called null modem) 如果目标计算机运

SQLSERVER 切换数据库为单用户和多用户模式

有时候数据库在占用时,想做一些操作,无法操作.可以尝试将数据库切换为单用户模式来操作.操作完之后再切换回多用户模式. 命令如下: alter database 数据库名 set Single_user  --单用户alter database 数据库名 set multi_user   --多用户 或者 sp_dboption 数据库名,"single user",true  --单用户 sp_dboption 数据库名,"single user",false  -