内核编程之小试牛刀

来源:互联网 发布:php 采集微信文章内容 编辑:程序博客网 时间:2024/05/16 17:09

学习内核编程我们首先需要知道三个重要概念:驱动对象、设备对象、IRP
这三者之间有着紧密的联系,他们分别类似于Windows界面编程中的程序、窗口、消息,这样去理解比较容易理解。

内核编程必有三样
1、包含ntddk.h头文件
2、必须要有一个DriverEntry入口函数
3、必须要有一个驱动卸载函数

在这里我编写一个简单的驱动程序,主要为了展示编写内核驱动程序的步骤:
它是一个Ring3与Ring0之间读写文件的一段代码,在这里可以看到在Windows中CreateFile、ReadFile、WriteFile等等API是如何实现的。
首先,我们需要分别给设备和符号链接赋予一个名称

    //设备名称    UNICODE_STRING szDeviceName =         RTL_CONSTANT_STRING(L"\\Device\\Device_Name");    //符号链接名称    UNICODE_STRING szSymbolLinkName =        RTL_CONSTANT_STRING(L"\\DosDevices\\SymbolLink_Name");    PDEVICE_OBJECT pDevice = NULL;

第一步,创建一个设备,并且设置设备的通讯方式为缓冲区设备读写方式(知识点补充:设备的通讯方式有三种,缓冲区设备读写方式,直接读写方式,其他方式)

//1 创建一个设备    status = IoCreateDevice(        pDriver,        0,        &szDeviceName,        FILE_DEVICE_UNKNOWN,        0,        FALSE,        &pDevice        );    if (NT_SUCCESS(status)==FALSE)    {        KdPrint(("创建设备失败了%x", status));        return status;    }    pDevice->Flags |= DO_BUFFERED_IO;

第二步,给设备创建一个符号链接

//2 给设备创建一个符号连接    status = IoCreateSymbolicLink(&szSymbolLinkName, &szDeviceName);    if (NT_SUCCESS(status) == FALSE)    {        KdPrint(("创建符号连接失败了%x", status));        IoDeleteDevice(pDevice);        return status;    }

第三步,我们填写驱动对象的分发函数,先全部设置为默认处理函数,再分别对待不同IRP类型的消息进行不同的函数处理。

//3填写分发函数for (int i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)    {        pDriver->MajorFunction[i] = DefaultProc;    }    pDriver->MajorFunction[IRP_MJ_CREATE] = CreateProc;    pDriver->MajorFunction[IRP_MJ_READ] = ReadProc;    pDriver->MajorFunction[IRP_MJ_WRITE] = WriteProc;

这样,当用户层调用CreateFile、ReadFile、WriteFile等函数时就会发送各自对应的IRP类型消息,不同的函数对应不同的IRP消息类型,也对应着内核层不同的处理函数。

当用户调用WriteFile函数时,保存写入信息的缓冲区就会拷贝到内核层使用,等使用完以后,再拷贝到用户层。这个是由于我们设置设备通讯方式时设置的是缓冲区设备读写方式导致的。学习内核还是需要比较多的前置知识的,推荐书籍《X86/X64体系探索及编程》

原创粉丝点击