系統給每個進程定義了一個唯一標識該進程的非負正數,稱作進程標識符。網路進程標識符簡單的表示為網路中主進程表中的一個索引。
基本介紹
- 中文名:網路進程標識符
- 外文名:Network process identifier
- 定義:網路中主進程表中的一個索引
- 系統:Windows和Linux
- 保存位置:進程的PCB中
- 領域:計算機網路
概述,進程標識符,進程標識符屬性,進程的有效標識符,Linux進程標識符,
概述
系統給每個進程定義了一個唯一標識該進程的非負正數,稱作進程標識符。進程標識符可以簡單的表示為主進程表中的一個索引。當某一進程終止後,其標識符可以重新用作另一進程的標識符。不過,在任何時刻,一個標識符所代表的進程是唯一的。系統把標識符 0 和 1 保留給系統的兩個重要進程。進程 0 是調度進程,它按一定的原則把處理機分配給進程使用。進程 1 是初始化進程,它是程式/sbin/init 的執行。進程 1 是 UNIX 系統那其它進程的祖先,並且是進程結構的最終控制者。
進程標識符
進程標識符屬性
#include <sys/types.h>#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
若成功執行,返回相應ID,執行失敗則返回-1;
另外這裡面進程ID和父進程ID不能更改,其他都可以更改。
另外這裡面進程ID和父進程ID不能更改,其他都可以更改。
進程的有效標識符
實際⽤戶ID和實際⽤戶組ID:每個進程都有一個實際用戶標識符和一個實際組標識符,它們永遠是啟動該進程之用戶的用戶標識符和組標識符。也就是登錄用戶的uid和gid,比如我的Linux以lazyboy登錄,在Linux運行的所有命令的實際用戶ID都是lazyboy的uid,實際用戶組ID都是lazyboy的gid。(可以用id命令查)
有效⽤戶ID和有效⽤戶組ID:進程的有效用戶標識符和有效組標識符也許更重要些,它們被用來確定一個用戶能否訪問某個確定的檔案(該進程的訪問許可權)。在通常情況下,它們與實際用戶標識符和實際組標識符是一致的。但是,一個進程或其祖先進程可以設定程式檔案的置用戶標識符許可權或置組標識符許可權。這樣,當通過 exec 調用執行該程式時,其進程的有效用戶標識符就取自該檔案的檔案主的有效用戶標識符,而不是啟動該進程的用戶的有效用戶標識符。
另外,還有兩個系統調用可以用來設定進程的有效用戶標識符和有效組標識符,它們的使用格式如下:
另外,還有兩個系統調用可以用來設定進程的有效用戶標識符和有效組標識符,它們的使用格式如下:
#include <sys/types.h>#include <unistd.h>uid newuid;pid newgid;int status;/* 設定進程的有效用戶標識符 */status=setuid(newuid);/* 設定進程的有效組標識符 */status=getgid(newgid);
如果你不是超級用戶,那么你只能把進程的有效用戶標識符和有效組標識符設定成實際用戶和實際組標識符。超級用戶的話就可以隨意的設定有限標識符。
Linux進程標識符
每個進程都有一個實際用戶標識符和一個實際組標識符,它們永遠是啟動該進程之用戶的用戶標識符和組標識符。
進程的有效用戶標識符和有效組標識符也許更重要些,它們被用來確定一個用戶能否訪問某個確定的檔案。在通常情況下,它們與實際用戶標識符和實際組標識符是一致的。
有幾個系統調用可以用來得到進程的用戶標識符和組標識符,詳見下列程式:
/* 取進程的實際用戶標識符 */ uid=getuid(); /* 取進程的有效用戶標識符 */ euid=geteuid(); /* 取進程的實際組標識符 */ gid=getgid(); /* 取進程的有效組標識符 */ egid=getegid();
另外,還有兩個系統調用可以用來設定進程的有效用戶標識符和有效組標識符,它們的使用格式如下:
/* 設定進程的有效用戶標識符 */ status=setuid(newuid); /* 設定進程的有效組標識符 */ status=setgid(newid)
通過這兩個系統調用,進程可以改變自己的標識符,進而改變自己的許可權(因為Linux中許可權是通過標識符來判斷的)。比如一個root 建立的進程可以用這種方法放棄一部分的root 許可權而只保留工作所需的許可權。這樣可以提高系統的安全性。程式如下:
#include<stdio.h> #include<unistd.h> #include<sys/types.h> #include<fcntl.h> #include<stdlib.h> int main(int argc,char* argv[]) { int fd; fd = fork(); switch(fd){ case -1:{ perror("fork"); exit(-1); } break; case 0: { //開始進程用戶id和有效用戶id printf("uid=%d,euid=%d\n",getuid(),geteuid()); //設定用戶id為1000,改變用戶許可權 setuid(1000); //改變後的用戶id和有效用戶id printf("uid=%d,euid=%d\n",getuid(),geteuid()); //root用戶才能查看shadow檔案,測試許可權是否改變 execlp("cat","cat","/etc/shadow",NULL); } break; default: { //開始進程用戶id和有效用戶id printf("uid=%d,euid=%d\n",getuid(),geteuid()); //root用戶才能查看shadow檔案 execlp("cat","cat","/etc/shadow",NULL); } break; } return 0; }
在root許可權下運行結果:
[root@embedclub file]# ./a.out uid=0,euid=0 uid=1000,euid=1000 cat: /etc/shadow: 許可權不夠 uid=0,euid=0 root:$$MG0tTs8yWCPoKMrG$tVrZQKQ6IK52ucaSGfHIMKdVHB7zP.rpqD5GO/1w07eYQj0Jgue9S/UijUtyYYQa9Irm2vwj7r.DwaY.5IXIp0:15195:0:99999:7::: bin:*:14789:0:99999:7:::
需要注意的是,一旦root 進程通過這種方式放棄了root 特權,將無法再通過setuid()調用的方式重新獲得root權,因為一個非root 標識符的進程是無法設定root 標識符的。這時可以使用Linux的另外兩個系統調用seteuid()和setegid()。其調用方式和前兩個完全相同。但是它們是根據進程程式檔案的標識符來判斷設定的。因此,一個root 的程式檔案在任何時候都可以將自己重新seteuid()為root。
root下運行結果:
[root@embedclub file]# ./a.out uid=0,euid=0 uid=1000,euid=1000 setuid to root: Operation not permitted
以上例子說明不是超級用戶所引用的進程,只能把它的有效用戶表示符和有效組標識符重新設定成其實際用戶標識符和實際組標識符。超級用戶所引用的進程就可以自由進行其有效用戶標識符和有效組標識符的設定。
以上使用setuid()永久改變許可權,現在使用seteuid()暫時改變用戶許可權:
#include<stdio.h> #include<unistd.h> #include<sys/types.h> #include<fcntl.h> #include<stdlib.h> int main(int argc,char* argv[]){ //開始進程用戶id和有效用戶id printf("uid=%d,euid=%d\n",getuid(),geteuid()); //設定有效用戶id為1000,暫時改變用戶許可權 seteuid(1000); //改變後的用戶id和有效用戶id printf("uid=%d,euid=%d\n",getuid(),geteuid()); //設定有效用戶id為0,改變用戶許可權為自己 if(-1 == setuid(0)){ perror("setuid to root"); exit(-1); } //改變後的用戶id和有效用戶id printf("uid=%d,euid=%d\n",getuid(),geteuid()); return 0; }
運行結果:
#./a.outuid=0,euid=0uid=0,euid=1000uid=0,euid=0 [root@embedclub file]# ./a.out uid=0,euid=0 uid=0,euid=1000 uid=0,euid=0