Linux 进程线程详解
在 Linux 的 top 和 ps 命令中,默认看到最多的是 pid
(process ID),也许你也能看到 lwp(thread ID)
和 tgid(thread group ID for the thread group leader)
等等,而在 Linux 库函数和系统调用里也许你注意到了 pthread id
和 tid
等等。还有更多的 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,等于lwp
。tid
在系统提供的接口函数中更常用,比如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最后都归结到
pid
和lwp(tid)
上。所以理解各种ID,最终归结为理解pid
和lwp(tid)
的联系和区别。
下面的图是一张描述父子进程,线程之间关系的图。
上图很好地描述了用户视角(user view)和内核视角(kernel view)看到线程的差别:
- 从用户视角出发,在
pid 42
中产生的tid 44
线程,属于tgid 42
。甚至用ps
和top
的默认参数,你都无法看到tid 44
线程。 - 从内核视角出发,
tid 42
和tid 44
是独立的调度单元,可以把他们视为pid 42
和pid 44
。
需要指出的是,有时候在Linux中进程和线程的区分也是不是十分严格的。即使线程和进程混用,pid
和 tid
混用,根据上下文,还是可以清楚地区分对方想要表达的意思。上图中,从内核视角出发看到了 pid 44
,是从调度单元的角度出发,但是在 top
或 ps
命令中,你是绝对找不到一个 pid
为44的进程的,只能看到一个 lwp(tid)
为44的线程。