什么是内核线程?

37

我刚开始编写设备驱动程序,对于线程还很陌生,查阅了许多文档以获取有关线程的概念。仍然有一些疑问。

  1. 什么是内核线程?
  2. 它与用户线程有何不同?
  3. 这两个线程之间的关系是什么?
  4. 如何实现内核线程?
  5. 在哪里可以看到实现的输出?

有人能帮帮我吗? 谢谢。


2
你已经阅读过这个了吧?http://en.wikipedia.org/wiki/Thread_(computing) 这应该至少回答了你的一些问题。 - Bart
2
在类似的情境下,还有这个之前的回答。 - jogojapan
4个回答

29
  1. 内核线程是一个没有用户空间组件的 task_struct
  2. 除了缺乏用户空间外,它有不同的祖先(kthreadd 内核线程而不是 init 进程),并且由仅限内核的 API 创建,而不是使用 clonefork/exec 系统调用的序列。
  3. 两个内核线程都有 kthreadd 作为父进程。除此之外,内核线程与用户空间进程一样相互独立。
  4. 使用 kthread.h 头文件中的 kthread_run 函数/宏。您很可能需要编写内核模块以调用此函数,因此应查看Linux 设备驱动程序
  5. 如果您正在引用实现的文本输出(通过 printk 调用),则可以使用 dmesg 命令在内核日志中查看此输出。

19

内核线程是仅在内核模式下运行的内核任务;通常情况下,它不是通过fork()clone()系统调用创建的。一个示例是kworkerkswapd

如果您不知道内核线程是什么,那么您可能不应该实现内核线程。

谷歌提供了许多关于内核线程的页面,例如Frey的页面


2
只是提醒一下,内核线程的 task->mm 实际上是 NULL - Ilya Matveychikov

5

用户线程和栈:

每个线程都有自己的栈,以便它可以使用自己的局部变量,线程共享全局变量,这些全局变量是 Linux 可执行文件中 .data 或 .bss 部分的一部分。由于线程共享全局变量,因此在多线程应用程序中访问/修改全局变量时,我们使用同步机制如互斥锁。局部变量属于线程个体栈的一部分,因此不需要任何同步。

内核线程

内核线程源于在进程上下文中运行内核代码的需求。内核线程是工作队列机制的基础。本质上,内核线程是仅在内核模式下运行且没有用户地址空间或其他用户属性的线程。

要创建一个内核线程,请使用 kthread_create():

#include <linux/kthread.h>

structure task_struct *kthread_create(int (*threadfn)(void *data),
                                      void *data, const char namefmt[], ...);

内核线程和栈: 内核线程用于为内核执行后处理任务,如pdf刷新线程、workq线程等。 内核线程基本上是没有地址空间的新进程(可以使用带有所需标志的clone()调用创建),这意味着它们不能切换到用户空间。内核线程像普通进程一样可调度和可抢占。

内核线程有自己的堆栈,它们用来管理本地信息。

更多关于内核栈的信息:- https://www.kernel.org/doc/Documentation/x86/kernel-stacks


4
由于您在比较内核线程和用户线程,我认为您的意思是以下内容。
现在实现线程的正常方式是在内核中完成,因此可以将其视为“正常”线程。但是也可以在用户空间中使用信号(例如 SIGALRM)来实现线程,其处理程序保存当前进程状态(通常是寄存器),并将其更改为之前保存的另一个状态。在获得适当的内核线程支持之前,几个操作系统使用这种方法实现线程。这种方法可能更快,因为您不必进入内核模式,但在实践中它们已经逐渐消失了。
还有一种合作的用户线程,在其中一个线程运行时,直到调用特殊函数(通常称为 yield),然后以与上面的 SIGALRM 相似的方式切换到另一个线程。这里的优点是程序完全控制,这在具有时间考虑(例如游戏)时可能很有用。您也不必太关心线程安全。缺点是只能同时运行一个线程,因此此方法现在也不常见,因为处理器有多个核心。
内核线程是在内核中实现的。也许您想知道如何使用它们?最常见的方法是调用 pthread_create

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接