每个进程都由一个进程号来标识,其类型为 pid_t(无符号整型),进程号的范围:0~32767。进程号总是唯一的,但进程号可以重用。当一个进程终止后,其进程号就可以再次使用。
1.进程号分类 我们可以使用ps ajx命令查看系统的所有进程。
[root@iz2zefozq9h39txdb8s7npz ~]# ps ajx
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
0 1 1 1 ? -1 Ss 0 0:14 /usr/lib/systemd/systemd --system --deserialize 17
0 2 0 0 ? -1 S 0 0:00 [kthreadd]
2 3 0 0 ? -1 S 0 0:02 [ksoftirqd/0]
2 5 0 0 ? -1 S< 0 0:00 [kworker/0:0H]
2 7 0 0 ? -1 S 0 0:02 [migration/0]
2 8 0 0 ? -1 S 0 0:00 [rcu_bh]
2 9 0 0 ? -1 S 0 13:15 [rcu_sched]
2 10 0 0 ? -1 S 0 0:06 [watchdog/0]
2 11 0 0 ? -1 S 0 0:05 [watchdog/1]
2 12 0 0 ? -1 S 0 0:02 [migration/1]
2 13 0 0 ? -1 S 0 0:03 [ksoftirqd/1]
2 15 0 0 ? -1 S< 0 0:00 [kworker/1:0H]
2 17 0 0 ? -1 S 0 0:00 [kdevtmpfs]
2 18 0 0 ? -1 S< 0 0:00 [netns]
2 19 0 0 ? -1 S 0 0:00 [khungtaskd]
...
| 名称 | 含义 |
|---|---|
| 进程号(PID) | 标识进程的一个非负整型数。 |
| 父进程号(PPID) | 任何进程( 除 init 进程)都是由另一个进程创建,该进程称为被创建进程的父进程,对应的进程号称为父进程号(PPID)。如,A 进程创建了 B 进程,A 的进程号就是 B 进程的父进程号。 |
| 进程组号(PGID) | 进程组是一个或多个进程的集合。他们之间相互关联,进程组可以接收同一终端的各种信号,关联的进程有一个进程组号(PGID) |
| 进程名字(COMMAND) | 标识进程的名字。 |
系统允许一个进程创建新进程,新进程即为子进程,子进程还可以创建新的子进程,形成进程树结构模型。整个Linux系统的所有进程也是一个树形结构。树根是系统自动构造的,即在内核态下执行的 0 号进程,它是所有进程的祖先。进程号为 0 的进程通常是调度进程,常被称为交换进程(swapper)。由 0 号进程创建 1 号进程(内核态),1 号负责执行内核的部分初始化工作及进行系统配置,并创建若干个用于高速缓存和虚拟主存管理的内核线程。随后,1号进程调用 execve() 运行可执行程序 init,并演变成用户态1号进程,即init进程。所以,在 Linux 下面所有的进程都由 init 进程直接或者间接创建。
2.进程号操作函数
Linux 操作系统提供了三个获得进程号的函数 getpid()、getppid()、getpgid()。
#include <sys/types.h>
#include <unistd.h>
//获取本进程号(PID)
pid_t getpid(void);
//获取调用此函数的进程的父进程号(PPID)
pid_t getppid(void);
//获取进程组号(PGID)
pid_t getpgid(pid_tpid);
实例:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char const *argv[]){
int pid, ppid, pgid;
pid = getpid();
printf("pid = %d\n", pid);
ppid = getppid();
printf("ppid = %d\n", ppid);
pgid = getpgid(pid);
printf("pgid = %d\n", pgid);
return 0;
}
测试运行:
pid = 6027
ppid = 3292
pgid = 6027
注意:windows下子进程跟父进程之间的关系本事就是没什么关联的,不像Linux,windows也没有直接一个API可以得到父进程的ID,或者进程组的ID。因此以上代码一定要在linux环境下运行。