对于Linux用户空间进程,很容易确定哪些进程是多线程进程。您可以使用/proc/$pid/status.中的ps -eLf并查看线程数的NLWP值,该值也对应于“Thread:”值。显然,早在LinuxThreads时代,实现就不符合POSIX。但是This stackoverflow answer说"POSIX.1需要线程共享一个相同的进程ID“,这显然是在NPTL中纠正的。因此,对于NPTL,它允许使用命令(如/proc/$pid/task/ ps -eLf )来出色地显示线程,因为线程都共享相同的PID,您可以在下验证这一点,并查看属于“父”进程的所有线程子文件夹。
我找不到类似的线程分组在内核进程的“父”进程下产生,而且我怀疑实现上的差异,因为this answer下的评论说“您不能在内核空间中使用POSIX线程”,而漂亮的线程分组是POSIX特性。因此,在使用ps -eLf时,我从来没有看到有方括号的内核进程列出了多个线程,比如ksoftirqd/0或nfsd,这与init创建的用户空间进程不同。
(在用户空间中使用):
A single process can contain multiple threads, all of which are
executing the same program. These threads share the same global
memory (data and heap segments), but each thread has its own stack
(automatic variables).然而,对于内核“线程”,这正是我所看不到的,因为一个进程包含多个线程。
简而言之,我从来没有见过由'ps‘列出的进程中有哪个进程的NLWP (线程)值大于一个,这让我怀疑是否有任何内核进程像用户空间程序那样分叉/并行和多线程。这些实现有哪些不同之处?
实际示例:用于NFS进程的输出来自、ps、生长点、。
root 2 0.0 0.0 0 0 ? S Jan12 0:00 [kthreadd]
root 1546 0.0 0.0 0 0 ? S Jan12 0:00 \_ [lockd]
root 1547 0.0 0.0 0 0 ? S Jan12 0:00 \_ [nfsd4]
root 1548 0.0 0.0 0 0 ? S Jan12 0:00 \_ [nfsd4_callbacks]
root 1549 0.0 0.0 0 0 ? S Jan12 2:40 \_ [nfsd]
root 1550 0.0 0.0 0 0 ? S Jan12 2:39 \_ [nfsd]
root 1551 0.0 0.0 0 0 ? S Jan12 2:40 \_ [nfsd]
root 1552 0.0 0.0 0 0 ? S Jan12 2:47 \_ [nfsd]
root 1553 0.0 0.0 0 0 ? S Jan12 2:34 \_ [nfsd]
root 1554 0.0 0.0 0 0 ? S Jan12 2:39 \_ [nfsd]
root 1555 0.0 0.0 0 0 ? S Jan12 2:57 \_ [nfsd]
root 1556 0.0 0.0 0 0 ? S Jan12 2:41 \_ [nfsd]默认情况下,当您启动rpc.nfsd服务(至少使用init.d服务脚本)时,它会生成8个进程(或者至少它们有PID)。如果我想编写一个以nfsd“进程”为前端的多线程版本的NFS,它是作为内核模块实现的,为什么我不能将默认的8个不同的nfsd进程分组到一个PID下,并在其中运行8个线程,而不是(如所示--与用户空间进程不同)8个不同的PID?
相反,NSLCD是使用多线程的用户空间程序的一个例子:
UID PID PPID LWP C NLWP STIME TTY TIME CMD
nslcd 1424 1 1424 0 6 Jan12 ? 00:00:00 /usr/sbin/nslcd
nslcd 1424 1 1425 0 6 Jan12 ? 00:00:28 /usr/sbin/nslcd
nslcd 1424 1 1426 0 6 Jan12 ? 00:00:28 /usr/sbin/nslcd
nslcd 1424 1 1427 0 6 Jan12 ? 00:00:27 /usr/sbin/nslcd
nslcd 1424 1 1428 0 6 Jan12 ? 00:00:28 /usr/sbin/nslcd
nslcd 1424 1 1429 0 6 Jan12 ? 00:00:28 /usr/sbin/nslcdPID是相同的,但LWP是唯一的每个线程。
对函数的更新
kthreadd是运行在内核空间中的守护进程线程。原因是内核有时需要创建线程,但是在内核中创建线程非常困难。因此,如果需要的话,kthreadd是内核用来生成更新线程的线程。这个线程也可以访问用户空间地址空间,但不应该这样做。它由内核管理..。
K线程d()是守护进程的主函数(和主循环),守护进程是一个内核线程守护进程,它是所有其他内核线程的父进程。 因此,在所引用的代码中,有一个请求的创建。为了满足这个请求,kthreadd将读取它并启动一个内核线程。
发布于 2016-01-23 23:54:35
内核中没有进程的概念,所以您的问题没有真正的意义。Linux内核能够并且确实创建完全在内核上下文中运行的线程,但是所有这些线程都运行在相同的地址空间中。虽然相关线程通常有相关的名称,但没有按PID对类似线程进行分组。
如果多个内核线程正在处理相同的任务或以其他方式共享数据,那么它们需要通过锁定或其他并发算法来协调对该数据的访问。当然,在内核中不能使用pthread,但是可以使用内核互斥、等待队列等来获得与p线程互斥、条件变量等相同的功能。
调用这些执行上下文“内核线程”是一个相当好的名称,因为它们与用户空间进程中的多个线程非常相似。它们都共享(内核的)地址空间,但都有自己的执行上下文(堆栈、程序计数器等),并且各自独立调度并并行运行。另一方面,内核实际上实现了所有优秀的POSIX API抽象(在用户空间中的C库的帮助下),因此在实现的内部,我们没有完全的抽象。
https://stackoverflow.com/questions/34959506
复制相似问题