`

创建内核线程

阅读更多

在操作系统的最小执行单元就是线程,在内核中线程的概念更加容易看出来。比如说有的时候需要使用线程来完成一些任务,可是这些任务的工作量过大的时候系统处理这些任务就必须停下来等待。而等待的过程就大大的浪费了cup宝贵的时间,所以这个时候利用多线程去处理是最好的方法。

    在驱动里生成的线程一般是系统线程。PsCreateSystemThread 函数默认情况下创建的却是一个系统进程,它属于进程名为System,PID=4。同时PsCreateSystemThread 也可以创建用户线程,这取决于它的第四个参数ProcessHandle,如果它为空,则创建系统线程;如果它是一个进程句柄,则创建的是属于该指定进程的用户线程。

第六个参数StartRoutine是新线程的运行地址;第七个参数StartContext是新线程接收的参数。

    线程函数是一个非常重要的部分,它决定了该线程具有什么样的功能。线程函数必须按照如下规范声明:
VOID ThreadProc(IN PVOIDcontext);

    线程有个非常重要的问题:同步问题,虽然多线程并不是真正的并发运行,但由于 CPU分配的时间片很短,看起来它们就像是并发运行的一样。所以我们要保证线程的同步。这里我们使用简单的KEVENT事件对象进行同步。在使用 KEVENT事件对象前,需要首先调用内核函数 KeInitializeEvent对其初始化

   VOID KeInitializeEvent(
      IN PRKEVENT Event,
      IN EVENT_TYPE Type,
      IN BOOLEAN State);
    第一个参数 Event是初始化事件对象的指针;第二个参数Type表明事件的类型。事件分两种类型:一类是“通知事件”,对应参数为 NotificationEvent,另一类是“同步事件”,对应参数为 SynchronizationEvent;第三个参数State 如果为TRUE,则事件对象的初始化状态为激发状态,否则为未激发状态。如果创建的事件对象是“通知事件”,当事件对象变为激发态时,需要我们手动将其改回未激发态。如果创建的事件对象是“同步事件”,当事件对象为激发态时,如果遇到相应的 KeWaitFor****等内核函数,事件对象会自动变回到未激发态。
    设置事件的函数是 KeSetEvent,可通过该函数修改事件对象的状态。

    下面用一段简单的代码来说明问题。

  VOID
MyCreateThread()
{
 HANDLE   hThread;
 NTSTATUS  status;
 UNICODE_STRING ustrTest;
 
 // 初始化事件
 KeInitializeEvent(&kEvent, SynchronizationEvent, TRUE);
 RtlInitUnicodeString(&ustrTest, L"Just for test!");

 // 创建线程
 status = PsCreateSystemThread(&hThread, 0, NULL, NULL, NULL, MyThreadFunc, (PVOID)(&ustrTest));
 if (!NT_SUCCESS(status))
 {
  KdPrint(("[Test] CreateThread  Failed!"));
 }
 
 ZwClose(hThread);
 // 等待事件
 KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, 0);
}


VOID
MyThreadFunc(
    IN PVOID context
    )
{
 PUNICODE_STRING str = (PUNICODE_STRING)context;
 KdPrint(("[Test] %d : %wZ", (int)PsGetCurrentProcessId(), str));
 
 // 设置事件对象
 KeSetEvent(&kEvent, 0, FALSE);

 // 结束线程
 PsTerminateSystemThread(STATUS_SUCCESS);
}
程序运行如图:

天书夜读学习笔记之五—创建内核线程 - Faust - f4u5t的博客

分享到:
评论

相关推荐

    系统线程(内核线程)和用户线程区别 - 简书.pdf

    系统线程(内核线程)是由操作系统内核创建和撤销的线程,内核维护进程及线程的上下文信息以及线程切换。系统线程的优点是当有多个处理机时,一个进程的多个线程可以同时执行,缺点是由内核进行调度,创建和销毁系统...

    计算机操作系统实验_创建GeekOS内核线程.pdf

    计算机操作系统实验_创建GeekOS内核线程.pdf

    内核创建线程

    内核创建用户线程,实现稳定win7注入,在x86与x64平台下测试通过

    易语言创建线程

    易语言创建线程源码,创建线程,创建扩展线程_,关闭内核对象_,创建线程_

    基于内核线程的创建、使用和退出以及延时宏的补充说明介绍

    本篇文章是对内核线程的创建、使用和退出以及延时宏的补充说明介绍进行了叙述。需要的朋友参考下

    西工大计算机操作系统实验-创建GeekOS内核线程.doc

    西工大计算机操作系统实验-创建GeekOS内核线程.doc

    MFC两个线程中用事件内核对象通信

    MFC两个线程中用事件内核对象通信,VS2013编写的简单的实例。win10 64位电脑上使用过。创建了两个线程,创建了一个事件内核对象,里面用到了WaitForSingleObject函数。

    内核线程注入x64

    Win764位下通过驱动Attach到目标进程下再调用NtCreateThreadEx函数创建线程执行ShellCode来注入Dll。

    第5章 内核线程1

    写在前面在本章中,同学们会了解到如下知识。学习使用位图来将进行资源管理。实现页内存分配。学习内核线程的创建、调度和回收。页内存分配位图位图,BitMap,是用于

    内核线程注入x86

    主要通过Ring0层驱动Attach到目标进程然后调用NtCreateThreadEx来执行ShellCode,ShellCode做了一个注入Dll的简单行为。

    虚拟还原功能的源代码

    2 FileDiskCreateDevice:调用IoCreateDevice创建设备,KeInitializeEvent初始化事件对象,PsCreateSystemThread创建内核线程,入口函数是FileDiskThread,传入的函数参数为IoCreateDevice返回的设备对象。...

    内核线程中获取接收到的信号

    在测试开发的内核模块时,发现了一个BUG:在模块没有卸载时使用reboot命令重启系统的话,系统重启不了,查看日志发现在创建的内核线程中陷入了死循环,导致系统无法重启。检查了代码,发现产生问题的原因是当系统...

    Java与线程.pdf

    线程的实现有两种方式:用户线程和内核线程。 用户线程是在用户态中实现的,不需要内核的帮助。它的建立、同步、销毁和调度完全在用户态中完成,因此操作速度快且消耗低。然而,用户线程没有系统内核的支持,所有的...

    精通LINUX设备驱动程序开发

    3.1.1 创建内核线程 37 3.1.2 进程状态和等待队列 41 3.1.3 用户模式辅助程序 42 3.2 辅助接口 43 3.2.1 链表 44 3.2.2 散列链表 49 3.2.3 工作队列 49 3.2.4 通知链 51 3.2.5 完成接口 54 3.2.6...

    《精通Linux 设备驱动程序开发》.(Sreekrishnan).pdf

    3.1.1 创建内核线程37 3.1.2 进程状态和等待队列41 3.1.3 用户模式辅助程序42 3.2 辅助接口43 3.2.1 链表44 3.2.2 散列链表49 3.2.3 工作队列49 3.2.4 通知链51 3.2.5 完成接口54 3.2.6 kthread...

    西北工业大学计算机学院计算机操作系统实验报告一 创建GeekOS

    2022瓜大计算机学院计算机操作系统实验报告一 ---- 创建GeekOS内核线程,实验报告包含完整的操作流程和相关代码,内容详尽 示例: 1.编写操作系统引导扇区代码,并在虚拟机中运行。 2.创建一个线程,实现从键盘接收...

    操作系统课程实验.rar

    (1) 设计一个模块,要求列出系统中所有内核线程的程序名、PID 号、进程状态及 进程优先级。 (2) 设计一个带参数的模块,其参数为某个进程的 PID 号,该模块的功能是列出该 进程的家族信息,包括父进程、兄弟进程和...

Global site tag (gtag.js) - Google Analytics