首页 > 代码库 > 进程控制(1):进程标识符

进程控制(1):进程标识符

    进程标识符(PID)是一个进程的基本属性,其作用类似于每个人的身份证号码。根据进程标识符,用户可以精确地定位一个进程。一个进程标识符唯一对应一个进程,而多个进程标识符可以对应同一个程序。本文将深入探讨进程标识符及其相关操作。


1 进程标识符

    每个进程在系统中都有唯一的一个ID标识它,这个ID就是进程标识符(PID)。因为其唯一,所以系统可以根据它准确定位到一个进程。进程标识符的类型为pid_t,其本质上是一个无符号整型的类型别名(typedef)。

    接下来,我们来简单介绍一个进程与程序的关系。所谓程序,不过是指可运行的二进制代码文件,把这种文件加载到内存中运行就得到了一个进程。同一个程序文件可以被加载多次成为不同的进程。因此,进程标识符和进程之间是一对一的关系,而与程序文件之间是多对一的关系。

技术分享

在Linux shell中,可以使用ps命令查看当前用户所使用的进程。

xiaomanon@xiaomanon-machine:~$ ps -u xiaomanon  PID TTY          TIME CMD 1296 ?        00:00:00 init 1357 ?        00:00:00 sh 1359 ?        00:00:00 sleep 1362 ?        00:00:01 dbus-daemon 1371 ?        00:00:00 upstart-event-b 1375 ?        00:00:00 window-stack-br 1383 ?        00:00:00 gnome-keyring-d 1393 ?        00:00:00 upstart-file-br 1410 ?        00:00:00 bamfdaemon 1414 ?        00:00:00 upstart-dbus-br 1418 ?        00:00:00 upstart-dbus-br 1419 ?        00:00:00 ibus-daemon 1428 ?        00:00:00 gvfsd 1460 ?        00:00:00 unity-settings- 1482 ?        00:00:00 hud-service 1492 ?        00:00:00 at-spi-bus-laun 1495 ?        00:00:00 gvfsd-fuse 1497 ?        00:00:00 gnome-session 1498 ?        00:00:00 dbus-daemon 1506 ?        00:00:00 ibus-dconf 1507 ?        00:00:00 ibus-ui-gtk3 1510 ?        00:00:01 unity-panel-ser 1512 ?        00:00:00 ibus-x11 1523 ?        00:00:00 at-spi2-registr 1600 ?        00:00:00 indicator-messa 1605 ?        00:00:00 indicator-bluet 1610 ?        00:00:00 indicator-keybo 1615 ?        00:00:00 indicator-power 1625 ?        00:00:00 indicator-datet 1627 ?        00:00:00 indicator-sound 1630 ?        00:00:00 indicator-print 1635 ?        00:00:00 indicator-sessi 1653 ?        00:00:00 indicator-appli 1666 ?        00:00:00 evolution-sourc 1680 ?        00:00:00 pulseaudio 1733 ?        00:00:00 ibus-engine-sim 1793 ?        00:00:00 dconf-service 1795 ?        00:00:00 notify-osd 1860 ?        00:00:05 compiz 1901 ?        00:00:00 evolution-calen 1916 ?        00:00:00 unity-fallback- 1929 ?        00:00:00 nautilus 1933 ?        00:00:00 polkit-gnome-au 1937 ?        00:00:01 nm-applet 1945 ?        00:00:00 vmtoolsd 1998 ?        00:00:00 gvfs-udisks2-vo 2023 ?        00:00:00 gvfs-mtp-volume 2029 ?        00:00:00 gvfs-afc-volume 2033 ?        00:00:00 gconfd-2 2036 ?        00:00:00 gvfs-gphoto2-vo 2059 ?        00:00:00 gvfsd-trash 2078 ?        00:00:00 gvfsd-burn 2100 ?        00:00:00 gvfsd-metadata 2105 ?        00:00:00 telepathy-indic 2112 ?        00:00:00 mission-control 2118 ?        00:00:00 signon-ui 2126 ?        00:00:00 gnome-terminal 2132 ?        00:00:00 gnome-pty-helpe 2133 pts/1    00:00:00 bash 2182 ?        00:00:00 zeitgeist-datah 2187 ?        00:00:00 zeitgeist-daemo 2193 ?        00:00:00 zeitgeist-fts 2197 ?        00:00:00 cat 2207 pts/1    00:00:00 ps

    第一列内容是进程标识符(PID),这个标识符是唯一的;最后一列内容是进程的程序文件名。我们可以从中间找到有多个进程对应同一个程序文件名的情况,这是因为有一些常用的程序被多次运行了,比如shell和vi编辑器等。

注意:如果ps命令不使用“-u 用户名”作为参数,将不能检查到后台运行的进程。

xiaomanon@xiaomanon-machine:~$ ps  PID TTY          TIME CMD 2133 pts/1    00:00:00 bash 2325 pts/1    00:00:00 ps

 


2 进程中重要的标识符

    每个进程都有6个重要的ID值,分别是:进程ID、父进程ID、有效用户ID、有效组ID、实际用户ID和实际组ID。这6个ID保存在内核中的数据结构中,有些时候用户程序需要得到这些ID。

    例如,在/proc文件系统中,每一个进程都拥有一个子目录,里面存有进程的信息。当使用进程读取这些文件时,应该先得到当前进程的ID才能确定进入哪一个进程的相关子目录。由于这些ID存储在内核之中,因此,Linux提供一组专门的接口函数来访问这些ID值。

    Linux环境下分别使用getpid()和getppid()函数来得到进程ID和父进程ID,分别使用getuid()和geteuid()函数来得到进程的用户ID和有效用户ID,分别使用getgid()和getegid()来获得进程的组ID和有效组ID,其函数原型如下:

#include <unistd.h>pid_t getpid(void);    //获取进程IDpid_t getppid(void);  //获取父进程IDuid_t getuid(void);    //获取用户IDuid_t geteuid(void);    //获取有效用户IDgid_t getgid(void);    //获取组IDgid_t getegid(void);    //获取有效组ID

    以上6个函数,如果执行成功,则返回对应的ID值;失败,则返回-1。除了进程ID和父进程ID这两个值不能够更改以外,其他的4个ID值在适当的条件下可以被更改。下面的示例程序用于获取当前进程的6个ID值并打印出来。

//Get ID information about current process#include <stdio.h>#include <unistd.h>int main(void){    printf("PID: %u\n", getpid());    printf("PPID: %u\n", getppid());    printf("UID: %u\n", getuid());    printf("EUID: %u\n", geteuid());    printf("GID: %u\n", getgid());    printf("EGID: %u\n", getegid());    return 0;}

程序运行效果如下:

xiaomanon@xiaomanon-machine:~/Documents/c_code$ ./getid PID: 2681PPID: 2133UID: 1000EUID: 1000GID: 1000EGID: 1000

 


3 参考文献

[1] 吴岳,Linux C程序设计大全,清华大学出版社

进程控制(1):进程标识符