← 返回首页
Linux高级程序设计(二十七)
发表时间:2021-11-15 10:47:08
进程号

每个进程都由一个进程号来标识,其类型为 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环境下运行。