跳到主要内容

Linux 进程线程详解

在 Linux 的 topps 命令中,默认看到最多的是 pid (process ID),也许你也能看到 lwp(thread ID)tgid(thread group ID for the thread group leader)等等,而在 Linux 库函数和系统调用里也许你注意到了 pthread idtid 等等。还有更多的 ID,比如 pgrp (process group ID), sid (session ID for the session leader)tpgid (tty process group ID for the process group leader)。概念太多可能很晕,但是只要对Linux的进程和线程的基本概念有准确的理解,这些 ID 的含义都迎刃而解。下面将介绍进程和线程的核心概念,并以一个示例程序来验证这些ID之间的关系。

Linux的进程和线程

Linux 的进程和线程有很多异同点,可以 Google 下。但只要能清楚地理解一下几点,则足够理解 Linux 中各种 ID 的含义。

  • 进程是资源分配的基本单位,线程是调度的基本单位
  • 进程是资源的集合,这些资源包括内存地址空间,文件描述符等等,一个进程中的多个线程共享这些资源。
  • CPU对任务进行调度时,可调度的基本单位 (dispatchable entity)是线程。如果一个进程中没有其他线程,可以理解成这个进程中只有一个主线程,这个主进程独享进程中的所有资源。
  • 进程的个体间是完全独立的,而线程间是彼此依存,并且共享资源。多进程环境中,任何一个进程的终止,不会影响到其他非子进程。而多线程环境中,父线程终止,全部子线程被迫终止(没有了资源)。

上述第一点说明是最基础的,也是最重要的。

初步理解各种ID。基本上按照重要程度从高到低,在分割线下方的IDs不太重要。

  • pid: 进程ID。

  • lwp: 线程ID。在用户态的命令(比如 ps)中常用的显示方式。

  • tid: 线程ID,等于 lwptid 在系统提供的接口函数中更常用,比如 syscall(SYS_gettid)syscall(__NR_gettid)

  • tgid: 线程组ID,也就是线程组 leader 的进程ID,等于 pid

  • pgid: 进程组ID,也就是进程组 leader 的进程ID。

  • pthread id: pthread 库提供的ID,生效范围不在系统级别,可以忽略。

  • sid: session ID for the session leader。

  • tpgid: tty process group ID for the process group leader。

    从上面的列表看出,各种ID最后都归结到 pidlwp(tid) 上。所以理解各种ID,最终归结为理解 pidlwp(tid) 的联系和区别。

下面的图是一张描述父子进程,线程之间关系的图。

img

上图很好地描述了用户视角(user view)和内核视角(kernel view)看到线程的差别:

  • 从用户视角出发,在 pid 42 中产生的 tid 44 线程,属于 tgid 42。甚至用 pstop 的默认参数,你都无法看到 tid 44 线程。
  • 从内核视角出发,tid 42tid 44 是独立的调度单元,可以把他们视为 pid 42pid 44

需要指出的是,有时候在Linux中进程和线程的区分也是不是十分严格的。即使线程和进程混用,pidtid 混用,根据上下文,还是可以清楚地区分对方想要表达的意思。上图中,从内核视角出发看到了 pid 44,是从调度单元的角度出发,但是在 topps 命令中,你是绝对找不到一个 pid 为44的进程的,只能看到一个 lwp(tid) 为44的线程。