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


    一.用户模式的信号灯

    信号灯内部有个计数器,可以理解信号灯内部有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
    ");
    	getchar();
    	return 0;
    }
    
    
    void Sub_1()
    {
    	WaitForSingleObject(__SemaphoreHandle, INFINITE); 
    	printf("Sub_1()
    ");
    	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()
    ");
    }
    VOID SeCreateSemaphore()
    {
    	HANDLE ThreadHandle = NULL;
    	KSEMAPHORE  Semaphore;
    	ULONG  Count = 0;
    	PVOID  ThreadObject = NULL;
    	KeInitializeSemaphore(&Semaphore, 2, 2);
    	Count = KeReadStateSemaphore(&Semaphore);
    	DbgPrint("Semaphore Count:%d
    ", Count);
    	KeWaitForSingleObject(&Semaphore, Executive, KernelMode, FALSE, NULL);
    	Count = KeReadStateSemaphore(&Semaphore);
    	DbgPrint("Semaphore Count:%d
    ", 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);
    
    }
    

      

  • 相关阅读:
    网络管理和nmcli命令的使用——网络接口配置-bonding实验步骤
    raid组合优缺点介绍和创建LVM实验个人笔记
    磁盘分区就是这么简单,电脑小白都能看懂的磁盘分区教程!
    C盘优化之桌面移动法,拯救你爆满的C盘!
    电脑软件打开也有讲究,电脑软件打开方式总结!
    电脑使用建议大全,注意这些细节可以让你的电脑更好用!
    CentOS服务器apache绑定多个域名的方法
    CentOS 7使用yum安装PHP5.6
    PhpMyAdmin 配置文件现在需要一个短语密码的解决方法
    CentOs 7.*中配置安装phpMyAdmin的完整步骤记录
  • 原文地址:https://www.cnblogs.com/lsh123/p/7367310.html
Copyright © 2020-2023  润新知