刘收获

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

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

一.用户模式的信号灯

信号灯内部有个计数器,可以理解信号灯内部有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时,也就是所有灯泡都熄灭时,当前线程进入睡眠状态,直到信号灯变成激发状态或者超时。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// 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函数。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#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);
 
}

  

posted on   沉疴  阅读(234)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示