最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解應(yīng)用程序與驅(qū)動(dòng)程序通信DeviceIoControl

 更新時(shí)間:2021年06月10日 15:28:55   作者:沉疴  
這種通信方式,就是驅(qū)動(dòng)程序和應(yīng)用程序自定義一種IO控制碼,然后調(diào)用DeviceIoControl函數(shù),IO管理器會(huì)產(chǎn)生一個(gè)MajorFunction為IRP_MJ_DEVICE_CONTROL,MinorFunction為自己定義的控制碼的IRP,系統(tǒng)就調(diào)用相應(yīng)的處理IRP_MJ_DEVICE_CONTROL的派遣函數(shù)

一、定義IO控制碼 

其實(shí)可以看作是一種通信協(xié)議

看看CTL_CODE原型:

#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
  ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
  )

可以看到,這個(gè)宏四個(gè)參數(shù),自然是一個(gè)32位分成了4部分,高16位存儲(chǔ)設(shè)備類(lèi)型,14~15位訪(fǎng)問(wèn)權(quán)限,2~13位操作功能,最后0,1兩位就是確定緩沖區(qū)是如何與I/O和文件系統(tǒng)數(shù)據(jù)緩沖區(qū)進(jìn)行數(shù)據(jù)傳遞方式,最常見(jiàn)的就是METHOD_BUFFERED。

自定義CTL_CODE:

#define IOCTL_Device_Function CTL_CODE(DeviceType, Function, Method, Access)

IOCTL_Device_Function:生成的IRP的MinorFunction

DeviceType:設(shè)備對(duì)象的類(lèi)型。設(shè)備類(lèi)型可參考:http://blog.csdn.net/liyun123gx/article/details/38058965

Function :自定義的IO控制碼。自己定義時(shí)取0x800到0xFFF,因?yàn)?x0到0x7FF是微軟保留的。

Method :數(shù)據(jù)的操作模式。

METHOD_BUFFERED:緩沖區(qū)模式

METHOD_IN_DIRECT:直接寫(xiě)模式

METHOD_OUT_DIRECT:直接讀模式

METHOD_NEITHER :Neither模式

Access:訪(fǎng)問(wèn)權(quán)限,可取值有:

FILE_ANY_ACCESS:表明用戶(hù)擁有所有的權(quán)限

FILE_READ_DATA:表明權(quán)限為只讀

FILE_WRITE_DATA:表明權(quán)限為可寫(xiě)

也可以 FILE_WRITE_DATA | FILE_READ_DATA:表明權(quán)限為可讀可寫(xiě),但還沒(méi)達(dá)到FILE_ANY_ACCESS的權(quán)限。

繼續(xù)介紹這個(gè)緩沖區(qū)數(shù)據(jù)傳遞方式Method:

Method表示Ring3/Ring0的通信中的內(nèi)存訪(fǎng)問(wèn)方式,有四種方式:

#defineMETHOD_BUFFERED0

#defineMETHOD_IN_DIRECT1

#defineMETHOD_OUT_DIRECT2

#defineMETHOD_NEITHER3

(1)如果使用METHOD_BUFFERED,表示系統(tǒng)將用戶(hù)的輸入輸出都經(jīng)過(guò)pIrp->AssociatedIrp.SystemBuffer來(lái)緩沖,因此這種方式的通信比較安全。

METHOD_BUFFERED方式相當(dāng)于對(duì)Ring3的輸入輸出都進(jìn)行了緩沖。

METHOD_BUFFERED方式:

(2)如果使用METHOD_IN_DIRECT或METHOD_OUT_DIRECT方式,表示系統(tǒng)會(huì)將輸入緩沖在pIrp->AssociatedIrp.SystemBuffer中,并將輸出緩沖區(qū)鎖定,然后在內(nèi)核模式下重新映射一段地址,這樣也是比較安全的。

METHOD_IN_DIRECT和METHOD_OUT_DIRECT可稱(chēng)為"直接方式",是指系統(tǒng)依然對(duì)Ring3的輸入緩沖區(qū)進(jìn)行緩沖,但是對(duì)Ring3的輸出緩沖區(qū)并沒(méi)有緩沖,而是在內(nèi)核中進(jìn)行了鎖定。這樣Ring3輸出緩沖區(qū)在驅(qū)動(dòng)程序完成I/O請(qǐng)求之前,都是無(wú)法訪(fǎng)問(wèn)的,從一定程度上保障了安全性。

這兩種方式,對(duì)于Ring3的輸入緩沖區(qū)和METHOD_BUFFERED方式是一致的。對(duì)于Ring3的輸出緩沖區(qū),首先由系統(tǒng)鎖定,并使用pIrp->MdlAddress來(lái)描述這段內(nèi)存,驅(qū)動(dòng)程序需要使用MmGetSystemAddressForMdlSafe函數(shù)將這段內(nèi)存映射到內(nèi)核內(nèi)存地址(OutputBuffer),然后可以直接寫(xiě)入OutputBuffer地址,最終在驅(qū)動(dòng)派遣例程返回后,由系統(tǒng)解除這段內(nèi)存的鎖定。

METHOD_IN_DIRECT和METHOD_OUT_DIRECT方式的內(nèi)存訪(fǎng)問(wèn)

METHOD_IN_DIRECT和METHOD_OUT_DIRECT方式的區(qū)別,僅在于打開(kāi)設(shè)備的權(quán)限上,當(dāng)以只讀權(quán)限打開(kāi)設(shè)備時(shí),METHOD_IN_DIRECT方式的IoControl將會(huì)成功,而METHOD_OUT_DIRECT方式將會(huì)失敗。如果以讀寫(xiě)權(quán)限打開(kāi)設(shè)備,兩種方式都會(huì)成功。

METHOD_IN_DIRECT和METHOD_OUT_DIRECT方式:

(3)如果使用METHOD_NEITHER方式,"其他方式",雖然通信的效率提高了,但是不夠安全。驅(qū)動(dòng)的派遣函數(shù)中輸入緩沖區(qū)可以通過(guò)I/O堆棧(IO_STACK_LOCATION)的stack->Parameters.DeviceIo Control.Type3InputBuffer得到。輸出緩沖區(qū)可以通過(guò)pIrp->UserBuffer得到。由于驅(qū)動(dòng)中的派遣函數(shù)不能保證傳遞進(jìn)來(lái)的用戶(hù)輸入和輸出地址,因此最好不要直接去讀寫(xiě)這些地址的緩沖區(qū)。應(yīng)該在讀寫(xiě)前使用ProbeForRead和ProbeForWrite函數(shù)探測(cè)地址是否可讀和可寫(xiě)。

METHOD_ NEITHER方式是不進(jìn)行緩沖的,在驅(qū)動(dòng)中可以直接使用Ring3的輸入輸出內(nèi)存地址,

驅(qū)動(dòng)程序可以通過(guò)pIrpStack->Parameters.DeviceIoControl.Type3InputBuffer得到Ring3的輸入緩沖區(qū)地址(其中pIrpStack是IoGetCurrentIrpStackLocation(pIrp)的返回);通過(guò)pIrp-> UserBuffer得到Ring3的輸出緩沖區(qū)地址。

由于METHOD_NEITHER方式并不安全,因此最好對(duì)Type3InputBuffer讀取之前使用ProbeForRead函數(shù)進(jìn)行探測(cè),對(duì)UserBuffer寫(xiě)入之前使用ProbeForWrite函數(shù)進(jìn)行探測(cè),當(dāng)沒(méi)有發(fā)生異常時(shí),再進(jìn)行讀取和寫(xiě)入操作。

METHOD_NEITHER方式:

二、定義驅(qū)動(dòng)設(shè)備名,符號(hào)鏈接名

定義好了IO控制碼CTL_CODE,第二步驅(qū)動(dòng)程序還要準(zhǔn)備驅(qū)動(dòng)設(shè)備名和符號(hào)鏈接名。

關(guān)于在Ring0層中要設(shè)置驅(qū)動(dòng)設(shè)備名的同時(shí)還要設(shè)置符號(hào)鏈接名的原因,是因?yàn)橹挥蟹?hào)鏈接名才可以被用戶(hù)模式下的應(yīng)用程序識(shí)別。

windows下的設(shè)備是以"\Device\[設(shè)備名]”形式命名的。

例如磁盤(pán)分區(qū)的c盤(pán),d盤(pán)的設(shè)備名稱(chēng)就是"\Device\HarddiskVolume1”,"\Device\HarddiskVolume2”, 當(dāng)然也可以不指定設(shè)備名稱(chēng)。

如果IoCreateDevice中沒(méi)有指定設(shè)備名稱(chēng),那么I/O管理器會(huì)自動(dòng)分配一個(gè)數(shù)字作為設(shè)備的名稱(chēng)。

例如"\Device\00000001"。\Device\[設(shè)備名],不容易記憶,通常符號(hào)鏈接可以理解為設(shè)備的別名,更重要的是設(shè)備名,只能被內(nèi)核模式下的其他驅(qū)動(dòng)所識(shí)別,而別名可以被用戶(hù)模式下的應(yīng)用程序識(shí)別,例如c盤(pán),就是名為"c:"的符號(hào)鏈接,其真正的設(shè)備對(duì)象是"\Device\HarddiskVolume1”,所以在寫(xiě)驅(qū)動(dòng)時(shí)候,一般我們創(chuàng)建符號(hào)鏈接,即使驅(qū)動(dòng)中沒(méi)有用到,這也算是一個(gè)好的習(xí)慣吧。

驅(qū)動(dòng)中符號(hào)鏈接名是這樣寫(xiě)的

L"\\??\\HelloDDK" --->\??\HelloDDK

或者

L"\\DosDevices\\HelloDDK"--->\DosDevices\HelloDDK

在應(yīng)用程序中,符號(hào)鏈接名:

L"\\\\.\\HelloDDK"-->\\.\HelloDDK

DosDevices的符號(hào)鏈接名就是??, 所以"\\DosDevices\\XXXX"其實(shí)就是\\??\\XXXX

#define DEVICE_OBJECT_NAME  L"\\Device\\BufferedIODeviceObjectName"
//設(shè)備與設(shè)備之間通信
#define DEVICE_LINK_NAME    L"\\DosDevices\\BufferedIODevcieLinkName"
//設(shè)備與Ring3之間通信

三、將符號(hào)鏈接名與設(shè)備對(duì)象名稱(chēng)關(guān)聯(lián) ,等待IO控制碼

驅(qū)動(dòng)程序要做的最后一步,先用IoCreateDevice函數(shù)創(chuàng)建設(shè)備對(duì)象,再用IoCreateSymbolicLink將符號(hào)鏈接名與設(shè)備對(duì)象名稱(chēng)關(guān)聯(lián),大功告成,等待IO控制碼。

 //創(chuàng)建設(shè)備對(duì)象名稱(chēng)
RtlInitUnicodeString(&DeviceObjectName,DEVICE_OBJECT_NAME);
//創(chuàng)建設(shè)備對(duì)象
Status = IoCreateDevice(DriverObject,NULL,
    &DeviceObjectName,
    FILE_DEVICE_UNKNOWN,
    0, FALSE,
    &DeviceObject);
if (!NT_SUCCESS(Status))
{
    return Status;
}
 
//創(chuàng)建設(shè)備連接名稱(chēng)
RtlInitUnicodeString(&DeviceLinkName, DEVICE_LINK_NAME);
//將設(shè)備連接名稱(chēng)與設(shè)備名稱(chēng)關(guān)聯(lián)
Status = IoCreateSymbolicLink(&DeviceLinkName,&DeviceObjectName);
 
if (!NT_SUCCESS(Status))
{
    IoDeleteDevice(DeviceObject);
    return Status;
}       

四、應(yīng)用程序獲取設(shè)備句柄,發(fā)送IO控制碼

驅(qū)動(dòng)程序鋪墊打理好之后,應(yīng)用程序就可以由符號(hào)鏈接名通過(guò)CreateFile函數(shù)獲取到設(shè)備句柄DeviceHandle,再用本場(chǎng)的主角,DeviceIoControl通過(guò)這個(gè)DeviceHandle發(fā)送控制碼了。

先看看這兩個(gè)函數(shù):

BOOL WINAPI DeviceIoControl(
  _In_         HANDLE hDevice,       //CreateFile函數(shù)打開(kāi)的設(shè)備句柄
  _In_         DWORD dwIoControlCode,//自定義的控制碼
  _In_opt_     LPVOID lpInBuffer,    //輸入緩沖區(qū)
  _In_         DWORD nInBufferSize,  //輸入緩沖區(qū)的大小
  _Out_opt_    LPVOID lpOutBuffer,   //輸出緩沖區(qū)
  _In_         DWORD nOutBufferSize, //輸出緩沖區(qū)的大小
  _Out_opt_    LPDWORD lpBytesReturned, //實(shí)際返回的字節(jié)數(shù),對(duì)應(yīng)驅(qū)動(dòng)程序中pIrp->IoStatus.Information。
  _Inout_opt_  LPOVERLAPPED lpOverlapped //重疊操作結(jié)構(gòu)指針。同步設(shè)為NULL,DeviceIoControl將進(jìn)行阻塞調(diào)用;否則,應(yīng)在編程時(shí)按異步操作設(shè)計(jì)
);
HANDLE CreateFile(
  LPCTSTR lpFileName,                         //打開(kāi)的文件名
  DWORD dwDesiredAccess,                    //訪(fǎng)問(wèn)權(quán)限
  DWORD dwShareMode,                      //共享模式
  LPSECURITY_ATTRIBUTES lpSecurityAttributes,   //安全屬性
  DWORD dwCreationDisposition,               //文件存在與不存在時(shí)的文件創(chuàng)建模式
  DWORD dwFlagsAndAttributes,                //文件屬性設(shè)定(隱藏、只讀、壓縮、指定為系統(tǒng)文件等)
  HANDLE hTemplateFile                       //文件副本句柄
);

五、總結(jié)DeviceIoControl的通信流程

1.驅(qū)動(dòng)程序和應(yīng)用程序自定義好IO控制碼 (CTL_CODE宏 四個(gè)參數(shù),32位,4部分,存儲(chǔ)設(shè)備類(lèi)型,訪(fǎng)問(wèn)權(quán)限,操作功能,緩沖區(qū)數(shù)據(jù)傳遞方式(四種))

2.驅(qū)動(dòng)程序定義驅(qū)動(dòng)設(shè)備名,符號(hào)鏈接名, 將符號(hào)鏈接名與設(shè)備對(duì)象名稱(chēng)關(guān)聯(lián) ,等待IO控制碼(IoCreateDevice,IoCreateSymbolicLink)

3.應(yīng)用程序由符號(hào)鏈接名通過(guò)CreateFile函數(shù)獲取到設(shè)備句柄DeviceHandle,再用本場(chǎng)的主角,DeviceIoControl通過(guò)這個(gè)設(shè)備句柄發(fā)送控制碼給派遣函數(shù)。

六、源代碼

BufferedIO.h

#pragma once
#include <ntifs.h>

#define CTL_SYS \
    CTL_CODE(FILE_DEVICE_UNKNOWN,0x830,METHOD_BUFFERED,FILE_ANY_ACCESS)

#define DEVICE_OBJECT_NAME  L"\\Device\\BufferedIODeviceObjectName"
//設(shè)備與設(shè)備之間通信
#define DEVICE_LINK_NAME    L"\\DosDevices\\BufferedIODevcieLinkName"
//設(shè)備與Ring3之間通信
VOID DriverUnload(PDRIVER_OBJECT DriverObject);
NTSTATUS PassThroughDispatch(PDEVICE_OBJECT  DeviceObject, PIRP Irp);
NTSTATUS ControlThroughDispatch(PDEVICE_OBJECT  DeviceObject, PIRP Irp);

BufferedIO.c

#include "BufferedIO.h"

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegisterPath)
{
    NTSTATUS Status = STATUS_SUCCESS;
    PDEVICE_OBJECT  DeviceObject = NULL;
    UNICODE_STRING  DeviceObjectName;
    UNICODE_STRING  DeviceLinkName;
    ULONG           i;
    //   棧
    //   堆
    //   全局(global Static Const)
    DriverObject->DriverUnload = DriverUnload;
 
    //創(chuàng)建設(shè)備對(duì)象名稱(chēng)
    RtlInitUnicodeString(&DeviceObjectName,DEVICE_OBJECT_NAME);
 
    //創(chuàng)建設(shè)備對(duì)象
    Status = IoCreateDevice(DriverObject,NULL,
        &DeviceObjectName,
        FILE_DEVICE_UNKNOWN,
        0, FALSE,
        &DeviceObject);
    if (!NT_SUCCESS(Status))
    {
        return Status;
    }
    //創(chuàng)建設(shè)備連接名稱(chēng)
    RtlInitUnicodeString(&DeviceLinkName, DEVICE_LINK_NAME);
 
    //將設(shè)備連接名稱(chēng)與設(shè)備名稱(chēng)關(guān)聯(lián)
    Status = IoCreateSymbolicLink(&DeviceLinkName,&DeviceObjectName);
 
    if (!NT_SUCCESS(Status))
    {
        IoDeleteDevice(DeviceObject);
        return Status;
    }
    //設(shè)計(jì)符合我們代碼的派遣歷程
    for (i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
    {
        DriverObject->MajorFunction[i] = PassThroughDispatch;   //函數(shù)指針
    }
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ControlThroughDispatch;
    return Status;
}
//派遣歷程
NTSTATUS PassThroughDispatch(PDEVICE_OBJECT  DeviceObject,PIRP Irp)
{
    Irp->IoStatus.Status = STATUS_SUCCESS;     //LastError()
    Irp->IoStatus.Information = 0;             //ReturnLength
    IoCompleteRequest(Irp, IO_NO_INCREMENT);   //將Irp返回給Io管理器
    return STATUS_SUCCESS;
}
NTSTATUS ControlThroughDispatch(PDEVICE_OBJECT  DeviceObject, PIRP Irp)
{
    NTSTATUS Status;
    ULONG_PTR Informaiton = 0;
    PVOID InputData = NULL;
    ULONG InputDataLength = 0;
    PVOID OutputData = NULL;
    ULONG OutputDataLength = 0;
    ULONG IoControlCode = 0;
    PIO_STACK_LOCATION  IoStackLocation = IoGetCurrentIrpStackLocation(Irp);  //Irp堆棧  
    IoControlCode = IoStackLocation->Parameters.DeviceIoControl.IoControlCode;
    InputData  = Irp->AssociatedIrp.SystemBuffer;
    OutputData = Irp->AssociatedIrp.SystemBuffer;
    InputDataLength  = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
    OutputDataLength = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength;
    switch (IoControlCode)
    {
    case CTL_SYS:
    {
        if (InputData != NULL&&InputDataLength > 0)
        {
            DbgPrint("%s\r\n", InputData);
        }
        if (OutputData != NULL&&OutputDataLength >= strlen("Ring0->Ring3") + 1)
        {
            memcpy(OutputData, "Ring0->Ring3", strlen("Ring0->Ring3") + 1);
            Status = STATUS_SUCCESS;
            Informaiton = strlen("Ring0->Ring3") + 1;
        }
        else
        {
            Status = STATUS_INSUFFICIENT_RESOURCES;   //內(nèi)存不夠
            Informaiton = 0;
        }
        break;
    }
    default:
        break;
    }
    Irp->IoStatus.Status = Status;             //Ring3 GetLastError();
    Irp->IoStatus.Information = Informaiton;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);  //將Irp返回給Io管理器
    return Status;                            //Ring3 DeviceIoControl()返回值
}
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
    UNICODE_STRING  DeviceLinkName;
    PDEVICE_OBJECT  v1 = NULL;
    PDEVICE_OBJECT  DeleteDeviceObject = NULL;
     
    RtlInitUnicodeString(&DeviceLinkName, DEVICE_LINK_NAME);
    IoDeleteSymbolicLink(&DeviceLinkName);
 
    DeleteDeviceObject = DriverObject->DeviceObject;
    while (DeleteDeviceObject != NULL)
    {
        v1 = DeleteDeviceObject->NextDevice;
        IoDeleteDevice(DeleteDeviceObject);
        DeleteDeviceObject = v1;
    }
}

IO.cpp

// 緩沖區(qū)IO.cpp : 定義控制臺(tái)應(yīng)用程序的入口點(diǎn)。
//
 
#include "stdafx.h"
#include <windows.h>
#define DEVICE_LINK_NAME    L"\\\\.\\BufferedIODevcieLinkName"
 
#define CTL_SYS \
    CTL_CODE(FILE_DEVICE_UNKNOWN,0x830,METHOD_BUFFERED,FILE_ANY_ACCESS)
int main()
{
    HANDLE DeviceHandle = CreateFile(DEVICE_LINK_NAME,
        GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);
    if (DeviceHandle==INVALID_HANDLE_VALUE)
    {
        return 0;
    }
    char BufferData = NULL;
    DWORD ReturnLength = 0;
    BOOL IsOk = DeviceIoControl(DeviceHandle, CTL_SYS,
        "Ring3->Ring0",
        strlen("Ring3->Ring0")+1,
        (LPVOID)BufferData,
        0,
        &ReturnLength,
        NULL);
    if (IsOk == FALSE)
    {
        int LastError = GetLastError();
 
        if (LastError == ERROR_NO_SYSTEM_RESOURCES)
        {
            char BufferData[MAX_PATH] = { 0 };
            IsOk = DeviceIoControl(DeviceHandle, CTL_SYS,
                "Ring3->Ring0",
                strlen("Ring3->Ring0") + 1,
                (LPVOID)BufferData,
                MAX_PATH,
                &ReturnLength,
                NULL);
 
            if (IsOk == TRUE)
            {
                printf("%s\r\n", BufferData);
            }
        }
    }
    if (DeviceHandle != NULL)
    {
        CloseHandle(DeviceHandle);
        DeviceHandle = NULL;
    }
    printf("Input AnyKey To Exit\r\n");
 
    getchar();
    return 0;
}

以上就是詳解應(yīng)用程序與驅(qū)動(dòng)程序通信DeviceIoControl的詳細(xì)內(nèi)容,更多關(guān)于應(yīng)用程序 驅(qū)動(dòng)程序通信 DeviceIoControl的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 搭建C語(yǔ)言開(kāi)發(fā)環(huán)境(Windows平臺(tái))匯總

    搭建C語(yǔ)言開(kāi)發(fā)環(huán)境(Windows平臺(tái))匯總

    本文給大家匯總了5種在WIN平臺(tái)下搭建C語(yǔ)言開(kāi)發(fā)環(huán)境的方法,包括一、在Windows平臺(tái)配置GNU環(huán)境,二、使用Sublime Test開(kāi)發(fā)C語(yǔ)言程序,三、使用VisualStudio開(kāi)發(fā)C語(yǔ)言程序,四、搭建EclipseCDT集成開(kāi)發(fā)環(huán)境,五、搭建Clion集成開(kāi)發(fā)環(huán)境,有需要的小伙伴可以參考下
    2015-11-11
  • C++實(shí)現(xiàn)模板方法模式的示例代碼

    C++實(shí)現(xiàn)模板方法模式的示例代碼

    這篇文章主要介紹了++實(shí)現(xiàn)模板方法模式,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • C語(yǔ)言求圓周率的簡(jiǎn)單實(shí)現(xiàn)方法

    C語(yǔ)言求圓周率的簡(jiǎn)單實(shí)現(xiàn)方法

    這篇文章主要介紹了C語(yǔ)言求圓周率的簡(jiǎn)單實(shí)現(xiàn)方法,涉及C語(yǔ)言數(shù)學(xué)運(yùn)算的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2016-05-05
  • 關(guān)于c++ 智能指針及 循環(huán)引用的問(wèn)題

    關(guān)于c++ 智能指針及 循環(huán)引用的問(wèn)題

    下面小編就為大家?guī)?lái)一篇關(guān)于c++ 智能指針及 循環(huán)引用的問(wèn)題。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-01-01
  • 詳解應(yīng)用程序與驅(qū)動(dòng)程序通信DeviceIoControl

    詳解應(yīng)用程序與驅(qū)動(dòng)程序通信DeviceIoControl

    這種通信方式,就是驅(qū)動(dòng)程序和應(yīng)用程序自定義一種IO控制碼,然后調(diào)用DeviceIoControl函數(shù),IO管理器會(huì)產(chǎn)生一個(gè)MajorFunction為IRP_MJ_DEVICE_CONTROL,MinorFunction為自己定義的控制碼的IRP,系統(tǒng)就調(diào)用相應(yīng)的處理IRP_MJ_DEVICE_CONTROL的派遣函數(shù)
    2021-06-06
  • C語(yǔ)言如何計(jì)算兩個(gè)數(shù)的最小公倍數(shù)

    C語(yǔ)言如何計(jì)算兩個(gè)數(shù)的最小公倍數(shù)

    這篇文章主要介紹了C語(yǔ)言如何計(jì)算兩個(gè)數(shù)的最小公倍數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • C語(yǔ)言關(guān)于二叉樹(shù)中堆的創(chuàng)建和使用整理

    C語(yǔ)言關(guān)于二叉樹(shù)中堆的創(chuàng)建和使用整理

    大家好,這里是針對(duì)二叉樹(shù)中堆結(jié)構(gòu)的順序儲(chǔ)存,整理出來(lái)一篇博客供我們一起復(fù)習(xí)和學(xué)習(xí),如果文章中有理解不當(dāng)?shù)牡胤?還希望朋友們?cè)谠u(píng)論區(qū)指出,我們相互學(xué)習(xí),共同進(jìn)步
    2022-08-08
  • C++小游戲教程之猜數(shù)游戲的實(shí)現(xiàn)

    C++小游戲教程之猜數(shù)游戲的實(shí)現(xiàn)

    這篇文章主要和大家詳細(xì)介紹如何利用C++做一個(gè)簡(jiǎn)易的猜數(shù)游戲,分為用戶(hù)猜數(shù)和系統(tǒng)猜數(shù)。文中的示例代碼講解詳細(xì) ,感興趣的小伙伴可以嘗試一下
    2022-11-11
  • 解析shell排序的實(shí)現(xiàn)代碼

    解析shell排序的實(shí)現(xiàn)代碼

    本篇文章是對(duì)shell排序的實(shí)現(xiàn)代碼進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • c++通過(guò)引用實(shí)現(xiàn)三個(gè)數(shù)字求最大值

    c++通過(guò)引用實(shí)現(xiàn)三個(gè)數(shù)字求最大值

    下面我們將通過(guò)這個(gè)例子來(lái)說(shuō)明引用的作為函數(shù)參數(shù)的使用方法。需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助
    2013-10-10

最新評(píng)論

平阳县| 读书| 会东县| 江西省| 蒙城县| 灌南县| 措勤县| 乐业县| 东海县| 巧家县| 贵港市| 石屏县| 泰宁县| 西畴县| 西乡县| 武强县| 桦南县| 新干县| 晋宁县| 崇文区| 灵丘县| 东宁县| 专栏| 万荣县| 正定县| 门源| 依兰县| 黄石市| 翼城县| 新兴县| 汉川市| 化隆| 伊川县| 留坝县| 肥西县| 辽宁省| 纳雍县| 体育| 平邑县| 永靖县| 南昌县|