在操作系统的最小执行单元就是线程,在内核中线程的概念更加容易看出来。比如说有的时候需要使用线程来完成一些任务,可是这些任务的工作量过大的时候系统处理这些任务就必须停下来等待。而等待的过程就大大的浪费了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);
}
程序运行如图:
分享到:
相关推荐
"EnumDrivers"可能是指枚举系统驱动程序的过程,这在查看内核线程时可能不直接相关,但有时驱动程序可能会创建内核线程,因此了解正在运行的驱动可能有助于分析内核线程的来源。 "getdata_int"和"getdata_str"可能...
创建内核线程时,内核提供了专门的函数,例如kernel_thread(),这个函数可以用来创建新的内核线程。使用这个函数时,需要指定要运行的函数和其参数,返回时,父线程会退出,子线程开始执行函数fn指向的代码。 一般...
2. 使用`kthread_create`创建内核线程,`wake_up_process`启动线程。 3. 内核线程函数通常是无限循环,通过`kthread_should_stop`检查是否需要退出。 4. `schedule_timeout`用于控制线程让出CPU并在指定时间后恢复...
### 创建内核线程 创建内核线程通常使用`kthread_create()`函数。这个函数接受一个函数指针`threadfn`作为线程要执行的任务,`data`参数是传递给线程函数的数据,`namefmt`用于指定线程的名字。例如: ```c struct...
计算机操作系统实验 - 创建GeekOS内核线程 一、实验目的分析 GeekOS中内核代码,掌握内核线程的实现原理 在计算机操作系统中,内核线程是操作系统的核心组成部分。内核线程是操作系统中最基本的执行单元,它负责...
系统线程(内核线程)是由操作系统内核创建和撤销的线程,内核维护进程及线程的上下文信息以及线程切换。系统线程的优点是当有多个处理机时,一个进程的多个线程可以同时执行,缺点是由内核进行调度,创建和销毁系统...
#### 创建内核线程:掌握核心技巧 创建内核线程涉及理解进程状态和等待队列的概念,这是实现高效异步处理的基础。内核线程的创建通常依赖于内核提供的API,这些API允许开发者指定线程的入口点函数、参数以及优先级...
内核创建用户线程,实现稳定win7注入,在x86与x64平台下测试通过
在Windows系统中,内核线程注入允许开发者在目标进程中创建新的线程,并执行特定的代码,比如ShellCode,这通常是出于调试、监控或恶意软件的目的。 首先,让我们深入理解“Ring0”层级。在x86架构的CPU中,存在四...
3. **关闭内核对象**:在创建线程后,线程句柄是一个内核对象,需要正确管理和释放。当线程完成其任务或者不再需要时,应调用`关闭内核对象`函数来释放资源,防止内存泄漏。正确关闭线程句柄是确保程序健壮性的重要...
线程是操作系统内核调度的基本单位,一个进程可以包含多个线程,它们共享进程的内存空间,各自拥有独立的执行流程。远程线程则是在目标进程上下文中创建的线程,它可以在目标进程中执行代码,而不必拥有该进程的源...
内核本身也是多线程的,能够创建内核线程以执行各种操作系统任务,如设备驱动、文件系统操作等。 #### 3. 进程的创建与终止 在Solaris中,进程的创建涉及到一系列复杂的步骤。首先,父进程通过fork()系统调用来...
- **2.2 内核线程A到内核线程B**:在内核态下,通过更新线程控制块(TCB)中的信息,保存当前线程的状态,并加载新线程的TCB,从而切换到另一个内核线程的内核栈。 - **2.3 内核线程B到用户程序**:当内核线程B...
2. 创建内核线程 你需要创建一个线程,该线程能响应键盘输入并在屏幕上显示。这涉及到对GeekOS内核线程结构的理解,以及对键盘中断处理的掌握。线程的创建通常涉及分配线程结构体、设置上下文、并将其加入到线程调度...
操作系统是计算机科学中的核心课程,而内核级线程(Kernel-Level Threads,KLT)是操作系统中多线程实现的一种重要方式。哈工大的操作系统实验8着重探讨了如何在内核层面实现线程机制,这对于理解和掌握操作系统的...
- **创建函数**:`kthread_create`/`kthread_create_on_node`用于创建内核线程。 - `struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), void *data, int node, const char *namefmt, ...)`...
与用户线程相比,内核线程的创建、调度和销毁等操作都需要通过操作系统内核完成,这使得它们对硬件资源的访问更为直接,但也导致了更高的开销。 本章主要关注的是内核线程以及相关的内存管理和数据结构——位图...
- 创建和销毁线程的开销较大,因为涉及到内核态的上下文切换。 - 系统调用的开销可能会增加,因为每次线程切换都需要经过内核。 总结来说,用户级线程更适合于轻量级的并发需求,而内核级线程则更适用于需要高效...