一个进程包含多个属性参数,通过使用 ps 命令,我们可以查看当前系统中有关进程的详细信息,例如:
[root@localhost ~]# ps -le F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIMECMD 4 S 0 1 0 0 80 0 - 718 - ? 00:00:02 init 1 S 0 2 0 0 80 0 - 0 - ? 00:00:00 kthreadd …省略部分输出…
可以看到,每个进程都包含 F、S、UID、PID 等属性,这些属性参数决定了进程被处理的先后顺序、能够访问的资源等,对于系统管理员和程序员都非常重要。
本节将带领大家认识几个常用的属性参数。
在前面章节已经讲过,系统为每个用户都分配了用于标识其身份的 ID 号(UID)。同样地,进程也有这样一个 ID 号,被称作 PID。
要知道,用 ID 确定进程的方法是非常有好处的,因为对于计算机而言,认识数字永远比认识一串字符方便得多,Linux 没有必要去理解那些对人类非常“有意义”的进程名。
不仅 Linux 自己使用 PID 来确定进程,还要求用户在管理进程时,也提供相应的 PID 号。事实上,几乎所有的进程管理工具接受的也都是 PID 号,而不是进程名。
在 Linux 中,所有的进程都必须由另一个进程创建(除了在系统引导时,由内核自主创建并安装的那几个进程)。当一个进程被创建时,创建它的那个进程被称作父进程,而这个进程则相应地被称作子进程。
子进程使用 PPID 指出谁是其“父亲”,很容易可以理解,PPID 指的就是其父进程的 PID。
注意,在以上的叙述中,多次用到了“创建”这个词,这是出于表述和理解上的方便,事实上,在 Linux 中进程是不能被“凭空”创建的,换句话说,Linux 没有提供一种系统调用让应用程序“创建”一个进程,应用程序只能通过克隆自己来产生新进程。
关于“子进程应该是其父进程的克隆体”这种说法,听起来的确有点让人困惑,读者如果对此感兴趣,可以阅读一些和 Linux 编程方面相关的文章。
只有进程的创建者和 root 用户才有权利对该进程进行操作,因此记录一个进程的创建者(也就是属主)就显得非常必要。进程的 UID 就是其创建者的用户 ID 号,用于标识进程的属主。
除此之外,Linux 还为进程保存了一个“有效用户 ID 号”,被称作 EUID。这个特殊的 UID 号用来确定进程对某些资源和文件的访问权限。在绝大部分情况下,进程的 UID 和 EUID 是一样的,除了著名的 setuid 程序。
那么,什么是 setuid 程序呢?前面讲了 passwd 命令,这个命令允许用户修改自己的登录口令。但读者是否考虑过这个问题,密码保存在 /etc/shadow 文件中,这个文件对普通用户是不可读的,那么用户为什么能够通过修改 shadow 文件来修改自己的口令呢?
这就是 setuid 的妙处了,通过使 passwd 在执行阶段具有文件所有者(也就是 root)的权限,让用户临时有了修改 shadow 文件的能力(当然这种能力是受到限制的)。因此,passwd 就是一个典型的 setuid 程序,其 UID 是当前执行这个命令的用户 ID,而 EUID 则是 root 用户的 ID(也就是 0)。
除此之外,Linux 还给进程分配了其他几个 UID,例如 saved UID 和 FSUID。这种多 UID 体系的设置非常耐人寻味,对它的解释超出了本教程的范围,有兴趣的读者可以自己查阅相关资料。
类似地,进程的 GID 是其创建者所属组的 ID 号。对应于 EUID,进程同样拥有一个 EGID 号,可以通过 setgid 程序来设置。坦率地讲,进程的 GID 号确实没有什么用处。一个进程可以同时属于多个组,如果要考虑权限的话,那么 UID 就足够了。相比较而言,EGID 在确定访问权限方面还发挥了一定的作用。
当然,进程的 GID 号也不是一无是处。当进程需要创建一个新文件的时候,这个文件将采用该进程的 GID。
顾名思义,进程的优先级决定了其受到 CPU“优待”的程度,优先级髙的进程能够更早地被处理,并获得更多的处理器时间。
Linux 内核会综合考虑一个进程的各种因素来决定其优先级,这些因素包括进程已经消耗的 CPU 时间、进程已经等待的时间等。在绝大多数情况下,决定进程何时被处理是内核的事情,不需要用户插手。
用户可以通过设置进程的“谦让度”来影响内核的想法。“谦让度”和“优先级”刚好是一对相反的概念,高“谦让度”意味着低“优先级”,反之亦然。需要注意的是,进程管理工具让用户设置的总是“谦让度”,而不是“优先级”。如果希望让一个进程更早地被处理,那么应该把它的谦让度设置得低一些,使其变得不那么“谦让”。
修改进程的谦让度可以使用 nice 和 renice 命令,这两个命令的具体用法,会在本章后续文章做详细介绍。