進程標識符(PID)是一個進程的基本屬性,其做用相似於每一個人的身份證號碼。根據進程標識符,用戶能夠精確地定位一個進程。一個進程標識符惟一對應一個進程,而多個進程標識符能夠對應同一個程序。本文將深刻探討進程標識符及其相關操做。shell
每一個進程在系統中都有惟一的一個ID標識它,這個ID就是進程標識符(PID)。由於其惟一,因此係統能夠根據它準肯定位到一個進程。進程標識符的類型爲pid_t,其本質上是一個無符號整型的類型別名(typedef)。bash
接下來,咱們來簡單介紹一個進程與程序的關係。所謂程序,不過是指可運行的二進制代碼文件,把這種文件加載到內存中運行就獲得了一個進程。同一個程序文件能夠被加載屢次成爲不一樣的進程。所以,進程與進程標識符之間是一對一的關係,而與程序文件之間是多對一的關係。session
在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編輯器等。app
注意:若是ps命令不使用「-u 用戶名」做爲參數,將不能檢查到後臺運行的進程。編輯器
xiaomanon@xiaomanon-machine:~$ ps PID TTY TIME CMD 2133 pts/1 00:00:00 bash 2325 pts/1 00:00:00 ps
每一個進程都有6個重要的ID值,分別是:進程ID、父進程ID、有效用戶ID、有效組ID、實際用戶ID和實際組ID。這6個ID保存在內核中的數據結構中,有些時候用戶程序須要獲得這些ID。函數
例如,在/proc文件系統中,每個進程都擁有一個子目錄,裏面存有進程的信息。當使用進程讀取這些文件時,應該先獲得當前進程的ID才能肯定進入哪個進程的相關子目錄。因爲這些ID存儲在內核之中,所以,Linux提供一組專門的接口函數來訪問這些ID值。ui
Linux環境下分別使用getpid()和getppid()函數來獲得進程ID和父進程ID,分別使用getuid()和geteuid()函數來獲得進程的用戶ID和有效用戶ID,分別使用getgid()和getegid()來得到進程的組ID和有效組ID,其函數原型以下:spa
#include <unistd.h> pid_t getpid(void); //獲取進程ID pid_t getppid(void); //獲取父進程ID uid_t getuid(void); //獲取用戶ID uid_t geteuid(void); //獲取有效用戶ID gid_t getgid(void); //獲取組ID gid_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: 2681 PPID: 2133 UID: 1000 EUID: 1000 GID: 1000 EGID: 1000
[1] 吳嶽,Linux C程序設計大全,清華大學出版社