内核函数PsCreateSystemThread负责创建新线程。该函数可以创建两种线程,一种是用户线程,它属于当前进程中的线程。另一种是系统线程,系统线程不属于当前用户进程,而是属于系统进程,一般PID为4,名字为“System”的进程。

    NTSTATUS
   PsCreateSystemThread(
   OUT PHANDLE ThreadHandle, //新创建的线程句柄
   IN ULONG DesiredAccess, //创建的权限
   IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,//线程的属性,一般设为NULL
   IN HANDLE ProcessHandle OPTIONAL,//指定创建用户线程还是系统线程。如果为NULL,则为系统进程,如果该值是一个进程句柄,则新创建的线程属于这个指定的进程。DDK提供的NTCurrentProcess可以得到当前进程的句柄。
   OUT PCLIENT_ID ClientId OPTIONAL,
   IN PKSTART_ROUTINE StartRoutine,//新线程的运行地址
   IN PVOID StartContext //新线程接收的参数
   );

  

在内核模式下创建的线程是无法自动退出的,必须使用PsTerminateSystemThread强制结束线程。

通过内核事件KEVENT和内核等待KeWaitForSingleObject来演示事件的创建过程。

  

	KEVENT Event;

	//创建一个同步事件
KeInitializeEvent(
&Event, //要初始化的KEVENT结构对象
SynchronizationEvent, //事件类型
FALSE);

      KeSetEvent(
        &Event, //被激活的事件
        IO_NO_INCREMENT, //被唤醒线程临时提升线程优先级的增量,传0
        FALSE); //If TRUE, the KeSetEvent call must be followed by a call to KeWaitForMultipleObjects, KeWaitForMutexObject, or KeWaitForSingleObject.

  

	KeWaitForSingleObject(
&Event, //同步对象的指针,
Executive, //等待的原因,一般为Executive
KernelMode, //等待模式,一般为KernelMode
FALSE, //指明等待是否为“警惕”的,一般为FALSE
NULL); //等待时间,如果为NULL,就表示无限期等待,直到同步对象变为激发态
DbgPrint("ThreadProcedure() Exit\r\n");
PsTerminateSystemThread(STATUS_SUCCESS);

  

总结一下代码流程:

    1.驱动程序KeInitializeEvent创建了一个内核事件

2.PsCreateSystemThread创建新的系统线程,将创建好的KEVENT结构传参给新创建的线程。 再调用KeSetEvent将事件激活

3.线程中调用KeWaitForSingleObject等待事件激活状态(受信),执行后续代码,最后PsTerminateSystemThread结束线程。

源代码:

KEvent.h

#pragma once
#include <ntifs.h>
#define DELAY_ONE_MICROSECOND (-10)
#define DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000) VOID DriverUnload(PDRIVER_OBJECT DriverObject);
VOID KSleep(LONG MilliSecond);
void ThreadProcedure(PVOID ParameterData);

KEvent.c

#include "KEvent.h"
//http://www.cnblogs.com/dacainiao/p/5923147.html
//同步事件(SynchronizationEvent)
//当事件对象为激发时,如遇到KeWaitForXX等内核函数,事件对象则自动变回未激发态
//通知事件(NotificationEvent)
//当事件对象为激发时,如遇到KeWaitForXX等内核函数,事件对象则不会变回未激发态
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegisterPath)
{
int i = 0;
NTSTATUS Status = STATUS_SUCCESS;
HANDLE ThreadHandle = NULL;
PDEVICE_OBJECT DeviceObject = NULL;
KEVENT Event; CLIENT_ID ClientID = {0}; DriverObject->DriverUnload = DriverUnload; //创建一个同步事件
KeInitializeEvent(
&Event, //要初始化的KEVENT结构对象
SynchronizationEvent, //事件类型
FALSE); //如果为真,初始为激发态 //创建一个通知事件
//KeInitializeEvent(&Event, NotificationEvent,
// FALSE); //创建一个System进程下运行的线程
for (i=0;i<2;i++)
{
Status = PsCreateSystemThread(
&ThreadHandle, //新创建的线程句柄
0, //创建的权限
NULL, //线程的属性,一般设为NULL
NtCurrentProcess(), //指定创建用户线程还是系统线程。如果为NULL,则为系统进程,如果该值是一个进程句柄,则新创建的线程属于这个指定的进程。DDK的NTCurrentProcess可以得到当前进程的句柄。
&ClientID,
(PKSTART_ROUTINE)ThreadProcedure, //新线程的运行地址
(PVOID)&Event); //新线程接收的参数
} KSleep(3000);
KeSetEvent(
&Event, //被激活的事件
IO_NO_INCREMENT, //被唤醒线程临时提升线程优先级的增量,传0
FALSE); //If TRUE, the KeSetEvent call must be followed by a call to KeWaitForMultipleObjects, KeWaitForMutexObject, or KeWaitForSingleObject. return Status;
} void ThreadProcedure(PVOID ParameterData)
{
KEVENT Event = *((PKEVENT)ParameterData);
NTSTATUS Status;
KeWaitForSingleObject(
&Event, //同步对象的指针,
Executive, //等待的原因,一般为Executive
KernelMode, //等待模式,一般为KernelMode
FALSE, //指明等待是否为“警惕”的,一般为FALSE
NULL); //等待时间,如果为NULL,就表示无限期等待,直到同步对象变为激发态
DbgPrint("ThreadProcedure() Exit\r\n");
PsTerminateSystemThread(STATUS_SUCCESS);
} VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
DbgPrint("DriverUnload()\r\n");
} VOID KSleep(LONG MilliSecond)
{
LARGE_INTEGER Interval = {0};
Interval.QuadPart = DELAY_ONE_MILLISECOND;
Interval.QuadPart *= MilliSecond;
KeDelayExecutionThread(KernelMode, 0, &Interval);
}

  

驱动程序多线程 PsCreateSystemThread的更多相关文章

  1. [5]windows内核情景分析---进程线程

    本篇主要讲述进程的启动过程.线程的调度与切换.进程挂靠 进程的启动过程: BOOL CreateProcess ( LPCTSTR lpApplicationName,                 ...

  2. 不明显的多线程编程的具体Bugs

    我们都知道,在编写多线程程序时,我们应该记住很多细节,比如锁,使用线程安全库等.这里有一个不太明显的bug的列表,特定于多线程程序.其中许多都没有在初学者的文档或教程中提到,但我认为每个使用线程的人最 ...

  3. Java 多线程之单例设计模式

    转载:https://segmentfault.com/a/1190000007504892 概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍两种:懒汉式单例.饿汉 ...

  4. iOS多线程实现1-pthread

    1 操作系统.进程.线程简单介绍 现在的程序都是在操作系统上跑,很少有裸机的,而且大部分的嵌入式应用也都支持操作系统,当然还有一些很低端的嵌入式设备没有操作系统. iPhone手机跑的是iOS操作系统 ...

  5. C#多线程操作界面控件的解决方案(转)

    C#中利用委托实现多线程跨线程操作 - 张小鱼 2010-10-22 08:38 在使用VS2005的时候,如果你从非创建这个控件的线程中访问这个控件或者操作这个控件的话就会抛出这个异常.这是微软为了 ...

  6. WinForm多线程学习文档

    基础篇 怎样创建一个线程 受托管的线程与 Windows线程 前台线程与后台线程 名为BeginXXX和EndXXX的方法是做什么用的 异步和多线程有什么关联 WinForm多线程编程篇 我的多线程W ...

  7. java多线程(一)——线程安全的单例模式

    概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建自己的唯一实例. 3. ...

  8. LR中Vugen的多进程与多线程(脚本命令行)

    Controller使用驱动程序(如mdrv.exe或r3vuser.exe)来运行Vuser.用户可以在Controller的run-time setting中选择Vuser的运行方式:多进程/多线 ...

  9. MongoDB的C#驱动程序教程(译) 转

    1.概述 本教程是10gen支持C#驱动程序MongoDB的介绍.假定您熟悉使用MongoDB,因此主要集中在如何使用C#访问MongoDB的. 它分为两个部分:C# 驱动程序 ,BSON图书馆.C# ...

随机推荐

  1. 解决 mininet gave up after 3 retries 问题

    解决 mininet gave up after 3 retries 问题 在通过mn启动mininet的时候遇到了如下问题: *** Creating network *** Adding cont ...

  2. HDU 6069 Counting Divisors(唯一分解定理+因子数)

    http://acm.hdu.edu.cn/showproblem.php?pid=6069 题意: 思路: 根据唯一分解定理,$n={a_{1}}^{p1}*{a2_{}}^{p2}...*{a_{ ...

  3. UVa 12186 工人的请愿书(树形DP)

    https://vjudge.net/problem/UVA-12186 题意: 一个老板和n个员工组成树状结构,每个员工都有自己的唯一上司,老板的编号为0,员工1~n,工人们打算签署一个志愿书给老板 ...

  4. poj 2480 Longge's problem 欧拉函数+素数打表

    Longge's problem   Description Longge is good at mathematics and he likes to think about hard mathem ...

  5. python 获取格式化时间

    #!/usr/bin/python # -*- coding: UTF- -*- import time localtime = time.asctime( time.localtime(time.t ...

  6. 使用CMake在Linux下编译tinyxml静态库

    环境:CentOS6.6+tinyxml_2_6_21.下载并解压tinyxml_2_6_2.zip unzip tinyxml_2_6_2.zip 2.在tinyxml文件夹里创建一个CMakeLi ...

  7. Codeforces 916B - Jamie and Binary Sequence (changed after round)

    思路: 先取出二进制的每一位,判断总个数是不是小于等于k,如果大于k则不能构成. 通过观察可以发现,每一位的一个可以转换成下一位的两个,因为要使最大位尽可能小,所以如果最大位的所有的个数都可以转换成下 ...

  8. 解决SpringBoot更新数据到MySQL乱码问题

    怀疑数据库没有采用UTF8编码. DB也是UTF8格式,没有问题. 怀疑Hibernate连接字符串问题. application.properties修改为通过utf8连接mysql,但是问题依然没 ...

  9. jquery ajax中 php前台后台文件中编辑都是uft-8,返回数据还是乱码

    jquery ajax中 前台后台文件中编辑都是uft-8,返回数据还是乱码 解决如下: 在后台处理文件里面需要再加编辑 header("Content-Type:text/html;cha ...

  10. LeetCode--111--最长公共前缀

    问题描述: 给定一个二叉树,找出其最小深度. 最小深度是从根节点到最近叶子节点的最短路径上的节点数量. 说明: 叶子节点是指没有子节点的节点. 示例: 给定二叉树 [3,9,20,null,null, ...