Dwarf Asked:2020-08-21 18:38:04 +0000 UTC2020-08-21 18:38:04 +0000 UTC 2020-08-21 18:38:04 +0000 UTC Linux 中的进程和线程 772 Linux中的进程和线程有什么区别?在 Dmitry Ketov 的书中,我读到进程由线程组成。但毕竟线程也有PID和属性,和普通进程一样,也可以衍生出其他线程。 linux 2 个回答 Voted Best Answer Fat-Zer 2020-08-22T08:33:20Z2020-08-22T08:33:20Z 定义 由于我们谈论的是 * nix 系统,因此依赖 POSIX 定义(免费翻译)并不是多余的: 线程(点燃线程,它也是一个线程¹)是作为进程的一部分执行(流控制)的线程之一。每个线程都有自己的线程 ID、调度程序优先级和策略errno、自己单独的键/值格式存储以及维护线程执行所需的资源。任何一个线程可以确定其地址的对象都将可供该进程中的所有线程使用,包括但不限于静态变量、由 访问malloc()的内存、其他可以通过地址直接访问的内存区域以及自动变量。 进程是一个地址空间,在其上下文中执行一个或多个线程,以及这些线程所需的资源。 注意:很多系统资源是由同一个进程的不同线程共享(shared)的。包括各种标识符(PID、PPID、PGID、SSID、各种SUID和SGID)、当前工作目录、根目录、umask和文件描述符。 从这里开始出现以下资源关联...... 该过程有: 地址空间(包括代码,以及静态和动态程序数据) 一个或多个线程 文件描述符表 其他系统资源和标识符 同时,进程的每个线程也有: 在实践中,执行流程意味着: 您的堆栈,因此,您的局部变量。 自己的处理器寄存器 线程 ID 调度程序中的优先级 errno可能还有其他一些线程局部变量。 Linux中线程实现的特点。 事实上, Linux线程被实现为“轻量级进程”。换句话说,它们在 linux 内核方面没有明显的区别:它们在内核中都表示为任务 task_struct,而例如它task->mm指向地址空间描述符(mm_struct)和task->files文件描述符表( files_struct) 并且对于一个进程的线程,这两个指针都将只指向一个对象。恕我直言,这主要是出于历史原因,尽管这样的实现并非没有它的美。 一切都会好起来的,但它引发了一个简直难以想象的术语混乱。例如,从用户空间的角度来看,进程ID(它返回的内容getpid(),对于进程中的所有线程必须相同)称为PID;但在内核方面,pid' 表示任务 ID,调用getpid()返回被调用的内容tgid(线程组 ID、线程组 ID )。但同时,/proc信息通过它以内核的形式输出。 此外,这个实现涉及一些技巧,部分在内核端,部分在用户空间端,例如, linux 中的系统调用 setuid(2)仅设置线程的 EUID,因此您必须借助 libc 包装器中的复杂操作来实现符合 POSIX 的行为,因此,在非 C 语言(如 Rust 或Go )中实现此功能存在问题。 但毕竟线程也有PID和属性,和普通进程一样, 不完全是:他们唯一拥有的是调度程序中的优先级和策略......其他一切都是错误和/或实现特性。 他们还可以产生其他线程。 是的,但值得注意的是,与进程生成不同,新线程的“父进程”是原始进程,而不是生成线程的进程。 ¹我更喜欢术语“流”,但为了避免术语与流混淆,我将在本节中使用“线程” becouse 2020-08-21T19:18:43Z2020-08-21T19:18:43Z 术语“线程”(thread,thread)是Process执行线程的简称。 执行线程是可以调度在 CPU 上运行的可执行指令序列。 线程也有一些状态并存储一些局部变量。 进程的线程共享其程序代码、全局变量和系统资源,但每个线程都有自己的程序计数器、寄存器内容和堆栈。 进程是分配给它的交互线程和资源的集合。 为了清楚起见,这是一张图片。
定义
由于我们谈论的是 * nix 系统,因此依赖 POSIX 定义(免费翻译)并不是多余的:
从这里开始出现以下资源关联......
该过程有:
同时,进程的每个线程也有:
errno可能还有其他一些线程局部变量。Linux中线程实现的特点。
事实上, Linux线程被实现为“轻量级进程”。换句话说,它们在 linux 内核方面没有明显的区别:它们在内核中都表示为任务
task_struct,而例如它task->mm指向地址空间描述符(mm_struct)和task->files文件描述符表(files_struct) 并且对于一个进程的线程,这两个指针都将只指向一个对象。恕我直言,这主要是出于历史原因,尽管这样的实现并非没有它的美。一切都会好起来的,但它引发了一个简直难以想象的术语混乱。例如,从用户空间的角度来看,进程ID(它返回的内容
getpid(),对于进程中的所有线程必须相同)称为PID;但在内核方面,pid' 表示任务 ID,调用getpid()返回被调用的内容tgid(线程组 ID、线程组 ID )。但同时,/proc信息通过它以内核的形式输出。此外,这个实现涉及一些技巧,部分在内核端,部分在用户空间端,例如, linux 中的系统调用
setuid(2)仅设置线程的 EUID,因此您必须借助 libc 包装器中的复杂操作来实现符合 POSIX 的行为,因此,在非 C 语言(如 Rust 或Go )中实现此功能存在问题。不完全是:他们唯一拥有的是调度程序中的优先级和策略......其他一切都是错误和/或实现特性。
是的,但值得注意的是,与进程生成不同,新线程的“父进程”是原始进程,而不是生成线程的进程。
¹我更喜欢术语“流”,但为了避免术语与流混淆,我将在本节中使用“线程”
术语“线程”(thread,thread)是Process执行线程的简称。
执行线程是可以调度在 CPU 上运行的可执行指令序列。
线程也有一些状态并存储一些局部变量。
进程的线程共享其程序代码、全局变量和系统资源,但每个线程都有自己的程序计数器、寄存器内容和堆栈。
进程是分配给它的交互线程和资源的集合。
为了清楚起见,这是一张图片。