接前一篇文章:Linux内核进程管理子系统有什么第八回 —— 进程主结构详解(4)
本文内容参考:
Linux内核进程管理专题报告_linux rseq-优快云博客
《趣谈Linux操作系统 核心原理篇:第三部分 进程管理》—— 刘超
《图解Linux内核 基于6.x》 —— 姜亚华 机械工业出版社
特此致谢!
进程管理核心结构 —— task_struct
1. 任务ID相关成员
上一回对于ps命令尤其是-eLo参数进行了讲解,并且对于ps -eLo命令的执行结果进行了解析。本回进一步进行解析。为了便于理解和回顾,再次贴出ps -eLo指令结果,以及初步解析。
$ ps -eLo pid,ppid,pgid,sid,lwp,nlwp,comm | grep process_test
765335 764210 765335 764210 765335 1 process_test
765336 765335 765335 764210 765336 3 process_test
765336 765335 765335 764210 765337 3 process_test
765336 765335 765335 764210 765338 3 process_test
上边你这段总结比较拗口、不够直观,在此再换一个直观的总结。
(1)第1行 —— 主进程
PID | PPID | PGID | SID | LWP | NLWP | COMMAND |
---|---|---|---|---|---|---|
进程ID | 父进程ID | 进程组ID | 会话ID | 线程ID | 线程组的线程数 | 程序名 |
765335 764210 765335 764210 765335 1 process_test
PID | PPID | PGID | SID | LWP | NLWP | COMMAND |
---|---|---|---|---|---|---|
765335 | 764210 | 765335 | 764210 | 765335 | 1 | process_test |
这一行对应的是例程中的主进程,也就是调用fork()的那个父进程。其:
- 进程id(实际上等同于线程组id)为765335;
- 父进程id为764210,这是执行./process_test的那个终端的进程id;
- 进程组id为765335。对于主进程而言,其进程组id就是自己的id;
- 会话id为764210。会话id是执行./process_test的那个终端的进程id;
- 线程id为765335。对于一个单线程的进程而言,其线程id与进程id相等。
- 线程组的线程数为1。由于没有创建线程,因此只有一个默认的主线程。
- 程序名为process_test。
(2)第2行 —— 子进程
PID | PPID | PGID | SID | LWP | NLWP | COMMAND |
---|---|---|---|---|---|---|
进程ID | 父进程ID | 进程组ID | 会话ID | 线程ID | 线程组的线程数 | 程序名 |
765336 765335 765335 764210 765336 3 process_test
PID | PPID | PGID | SID | LWP | NLWP | COMMAND |
---|---|---|---|---|---|---|
765336 | 765335 | 765335 | 764210 | 765336 | 3 | process_test |
这一行对应的是例程中的子进程,也就是调用fork()创建的那个子进程。其:
- 进程id(实际上等同于线程组id)为765336;
- 父进程id为765335。这就是上边那个主进程;
- 进程组id为765335。对于领导进程而言,其进程组id就是自己的id,反过来说,由于不是领导进程,因此其进程组id就不是子进程的id,而是主进程的id;
- 会话id为764210。会话id依然是执行./process_test的那个终端的进程id;
- 线程id为765336。对于一个多线程进程而言,每个线程都有一个不同的线程id,但进程id是相同的。
- 线程组的线程数为3。由于创建了两个线程,加上自己,一共3个线程。
- 程序名仍然是process_test。
(3)第3行 —— 线程1
PID | PPID | PGID | SID | LWP | NLWP | COMMAND |
---|---|---|---|---|---|---|
进程ID | 父进程ID | 进程组ID | 会话ID | 线程ID | 线程组的线程数 | 程序名 |
765336 765335 765335 764210 765337 3 process_test
PID | PPID | PGID | SID | LWP | NLWP | COMMAND |
---|---|---|---|---|---|---|
765336 | 765335 | 765335 | 764210 | 765337 | 3 | process_test |
这一行对应的是例程中的子进程,也就是调用fork()创建的那个子进程。其:
- 进程id(实际上等同于线程组id)为765336。线程1的进程id和主线程相同。
- 父进程id为765335。这就是上边那个主进程;
- 进程组id为765335。其进程组id就是主进程的id(注意,不是子进程的id);
- 会话id为764210。会话id依然是执行./process_test的那个终端的进程id;
- 线程id为765337。对于一个多线程进程而言,每个线程都有一个不同的线程id,但进程id是相同的。
- 线程组的线程数为3。由于子进程创建了两个线程,加上自己,一共3个线程。
- 程序名仍然是process_test。
(4)第4行 —— 线程2
PID | PPID | PGID | SID | LWP | NLWP | COMMAND |
---|---|---|---|---|---|---|
进程ID | 父进程ID | 进程组ID | 会话ID | 线程ID | 线程组的线程数 | 程序名 |
765336 765335 765335 764210 765338 3 process_test
PID | PPID | PGID | SID | LWP | NLWP | COMMAND |
---|---|---|---|---|---|---|
765336 | 765335 | 765335 | 764210 | 765338 | 3 | process_test |
这一行对应的是例程中的子进程,也就是调用fork()创建的那个子进程。其:
- 进程id(实际上等同于线程组id)为765336。线程2的进程id和主线程相同。
- 父进程id为765335。这就是上边那个主进程;
- 进程组id为765335。其进程组id就是主进程的id(注意,不是子进程的id);
- 会话id为764210。会话id依然是执行./process_test的那个终端的进程id;
- 线程id为765338。对于一个多线程进程而言,每个线程都有一个不同的线程id,但进程id是相同的。
- 线程组的线程数为3。由于子进程创建了两个线程,加上自己,一共3个线程。
- 程序名仍然是process_test。
由此可见,所谓Linux的进程和线程并没有本质区别,更多地是从是两者的实现层面来讲的,进程与线程的地位并不等同。比如提起进程id,线程(轻量级进程)并不被当作进程看待,类似的地方还有很多。在这类场景中,提起进程,并不包含轻量级进程即线程,而有些场景却是可以包含的。究其原因,Linux有自身的特性,但为了程序的可移植性,它必须遵循POSIX等一系列标准。比如,getpid系统调用POSIX规定返回进程id,如果一个轻量级 进程调用它返回的是线程id,那么在Linux上可以正常运行的程序,移植到其它操作系统就需要很多额外的工作。
更多内容请看下回。