《unix高级环境编程》进程控制——进程ID

来源:互联网 发布:收支软件 编辑:程序博客网 时间:2024/05/22 07:54

进程ID

        在unix系统中,每个进程都有一个非负整型表示的唯一进程ID。当一个进程终止时,进程ID可以重新被其他进程使用,为了防止误判,unix系统实现延迟重用算法,即新建的进程ID不同于最近终止进程所使用的ID。

        进程ID为0的是调度进程,也称为交换进程,是内核的一部分,不执行磁盘上的程序,因此也称为系统进程。进程ID为1的是init进程,负责在自举内核后启动一个unix系统,init通常读与系统有关的初始文件,并将系统引导到一个状态,该进程不是终止,它是一个普通的用户进程。下面函数是对进程ID的操作。

获取进程ID

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /* 进程ID */  
  2.   
  3. /* 
  4.  * 函数功能:获取进程ID; 
  5.  * 返回值:所调用进程的ID; 
  6.  * 函数原型: 
  7.  */  
  8.   #include <unistd.h>  
  9.   
  10.   pid_t getpid(void);  
  11.   
  12.   /* 
  13.    * 函数功能:获取父进程ID; 
  14.    * 返回值:所调用进程的父进程ID; 
  15.    * 函数原型: 
  16.    */  
  17.   pid_t getppid(void);  
  18.   
  19.   /* 
  20.    * 函数功能:进程实际用户ID; 
  21.    * 返回值:所调用进程的实际用户ID; 
  22.    * 函数原型: 
  23.    */  
  24.   uid_t getuid(void);  
  25.   
  26.   /* 
  27.    * 函数功能:进程有效用户ID; 
  28.    * 返回值:所调用进程的有效用户ID; 
  29.    * 函数原型: 
  30.    */  
  31.   uid_t geteuid(void);  
  32.   
  33.   /* 
  34.    * 函数功能:进程实际组ID; 
  35.    * 返回值:所调用进程的实际组ID; 
  36.    * 函数原型: 
  37.    */  
  38.   gid_t getgid(void);  
  39.   
  40.   /* 
  41.    * 函数功能:进程有效组ID; 
  42.    * 返回值:所调用进程的有效组ID; 
  43.    * 函数原型: 
  44.    */  
  45.   gid_t getegid(void);  
测试程序:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <unistd.h>  
  2. #include "apue.h"  
  3.   
  4. int main(void)  
  5. {  
  6.     printf("pid: %d.\n",getpid());  
  7.     printf("ppid: %d.\n",getppid());  
  8.     printf("uid: %d.\n",getuid());  
  9.     printf("euid: %d.\n",geteuid());  
  10.     printf("gid: %d.\n",getgid());  
  11.     printf("egid: %d.\n",getegid());  
  12.   
  13.     exit(0);  
  14. }  
输出结果:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. pid: 9136.  
  2. ppid: 3765.  
  3. uid: 1000.  
  4. euid: 1000.  
  5. gid: 1000.  
  6. egid: 1000.  

更改进程ID

       为了能够满足一些进程的访问权限,我们会对进程ID进行更改,主要是更改进程的用户ID和组ID。更改ID的规则如下:实际用户ID是指进程执行者;有效用户ID是指进程执行时对文件的访问权限;保存的设置用户ID是有效用户ID的副本,在执行exec调用时后能重新恢复原来的有效用户ID。注:以下的规则也适用于组ID。

  1. 若进程具有超级用户特权,则setuid函数将实际用户ID、有效用户ID,以及保存的设置用户ID设置为uid。
  2. 若进程没有超级用户权限,但是uid等于实际用户ID或保存的设置用户ID,则setuid函数将有效用户ID设置为uid。不改变实际用户和保存的设置用户ID。
  3. 若以上都不满足,则将errno设置为EPERM,并返回-1。
     关于内核维护的三个用户ID,应注意以下几点:

  1. 只有超级用户才可以修改实际用户ID。
  2. 仅当对程序文件设置了设置用户ID位时,exec函数才会设置有效用户ID。
  3. 保存的设置用户ID是由exec函数复制有效用户ID而得来的。
     改变三个用户ID的不同方法如下图所示:


      以下是更改进程ID的函数

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /* 更改进程ID */  
  2.   
  3. /* 
  4.  * 函数功能:设置用户或组ID(包括有效、实际和保存的设置用户的ID); 
  5.  * 返回值:若成功则返回0,若出错则返回-1; 
  6.  * 函数原型: 
  7.  */  
  8. #include <unistd.h>  
  9.   
  10. int setuid(uid_t uid);  
  11. int setgid(gid_t gid);  
  12.   
  13. /* 
  14.  * 函数功能:交换实际用户(组)ID和有效用户(组)ID; 
  15.  * 返回值:若成功则返回0,若出错则返回-1; 
  16.  */  
  17. #include <unistd.h>  
  18.   
  19. int setreuid(uid_t ruid, uid_t euid);  
  20. int setregid(gid_t rgid, gid_t egid);  
  21. /* 说明: 
  22.  * 若其中任一参数值为-1,则表示ID不变; 
  23.  */  
  24.   
  25. /* 
  26.  * 函数功能:更改有效用户或有效组ID; 
  27.  * 返回值:若成功则返回0,若出错则返回-1; 
  28.  * 函数原型: 
  29.  */  
  30. #include <unistd.h>  
  31.   
  32. int seteuid(uid_t uid);  
  33. int setegid(gid_t gid);  
0 0