Processes (进程)
本章描述进程是什么以及 Linux 如何创建、管理和删除系统中的进程。
进程执行操作系统中的任务。程序是存放在磁盘上的包括一系列机器代码指令和数据的可执行的映像,因此,是一个被动的实体。进程可以看作是一个执行中的计算机程序。它是动态的实体,在处理器执行机器代码指令时不断改变。处理程序的指令和数据,进程也包括程序计数器和其他 CPU 的寄存器以及包括临时数据(例如例程参数、返回地址和保存的变量)的堆栈。当前执行的程序,或者说进程,包括微处理器中所有的当前的活动。 Linux 是一个多进程的操作系统。进程是分离的任务,拥有各自的权利和责任。如果一个进程崩溃,它不应该让系统中的另一个进程崩溃。每一个独立的进程运行在自己的虚拟地址空间,除了通过的核心管理的机制之外无法影响其他的进程。
在一个进程的生命周期中它会使用许多系统资源。它会用系统的 CPU 执行它的指令,用系统的物理内存来它和它的数据。它会打开和使用文件系统中的文件,会直接或者间接使用系统的物理设备。 Linux 必须跟踪进程本身和它使用的系统资源以便管理公平地管理该进程和系统中的其他进程。如果一个进程独占了系统的大部分物理内存和 CPU ,对于其他进程就是不公平的。
系统中最宝贵的资源就是 CPU 。通常系统只有一个。 Linux 是一个多进程的操作系统。它的目标是让进程一直在系统的每一个 CPU 上运行,充分利用 CPU 。如果进程数多于 CPU (多数是这样),其余的进程必须等到 CPU 被释放才能运行。多进程是一个简单的思想:一个进程一直运行,直到它必须等待,通常是等待一些系统资源,等拥有了资源,它才可以继续运行。在一个单进程的系统,比如 DOS , CPU 被简单地设为空闲,这样等待的时间就会被浪费。在一个多进程的系统中,同一时刻许多进程在内存中。当一个进程必须等待时操作系统将 CPU 从这个进程拿走,并将它交给另一个更需要的进程。是调度程序选择了
下一次最合适的进程。 Linux 使用了一系列的调度方案来保证公平。
Linux 支持许多不同的可执行文件格式, ELF 是其中之一, 是另一个。 Linux 必须透明地管理这些文件,因为进程使用系统的共享的库。
4.1 Linux Processes ( Linux 的进程)
Linux 中,每一个进程用一个 task_struct (在 Linux 中 task 和 process 互用)的数据结构来表示,用来管理系统中的进程。 Task 向量表是指向系统中每一个 task_struct 数据结构的指针的数组。这意味着系统中最大进程数受 task 向量表的限制,缺省是 512 。当新的进程创建的时候,从系统内存中分配一个新的 task_struct ,并增加到 task 向量表中。为了更容易查找,用 current 指针指向当前运行的进程。
参见 include//sched.h
除了普通进程, Linux 也支持实时进程。这些进程必须对于外界事件迅速反应(因此叫做“实时”),调度程序必须和普通用户进程区分对待。虽然 task_struct 数据结构十分巨大、复杂,但是它的域可以分为以下的功能:
State 进程执行时它根据情况改变状态 (state) 。 Linux 进程使用以下状态:(这里漏掉了 SWAPPING ,因为看来没用到)
Running 进程在运行 ( 是系统的当前进程 ) 或者准备运行(等待被安排到系统的一个 CPU 上)
Waiting 进程在等待一个事件或资源。 Linux 区分两种类型的等待进程:可中断和不可中断的( interruptible and uninterruptible )。可中断的等待进程可以被信号中断,而不可中断的等待进程直接等待硬件条件,不能被任何情况中断。
Stopped 进程停止了,通常是接收到了一个信号。正在调试的进程可以在停止状态。
Zombie 终止的进程,因为某种原因,在 task 向量表重任旧有一个 task_struct 数据结构的条目。就想听起来一样,是一个死亡的进程。
Scheduling Information 调度者需要这个信息用于公平地决定系统中的进程哪一个更应该运行。
Identifiers 系统中的每一个进程都有一个进程标识符。进程标识符不是 task 向量表中的索引,而只是一个数字。每一个进程也都有用户和组( user and group )的标识符。用来控制进程对于系统中文件和设备的访问。
Inter-Process Communication Linux 支持传统的 UNIX-IPC 机制,即信号,管道和信号灯( semaphores ),也支持系统 V 的 IPC 机制,即共享内存、信号灯和消息队列。关于 Linux 支持的 IPC 机制在第 5 章中描述。
Links 在 Linux 系统中,没有一个进程是和其他进程完全无关的。系统中的每一个进程,除了初始的进程之外,都有一个父进程。新进程不是创建的,而是拷贝,或者说从前一个进程克隆的( cloned )。每一个进程的 task_struct 中都有指向它的父进程和兄弟进程(拥有相同的父进程的进程)以及它的子进程的的指针。在 Linux 系统中你可以用 pstree 命令看到正在运行的进程的家庭关系。
init(1)-+-crond(98)
|-emacs(387)
|-gpm(146)
|-inetd(110)
|-kerneld(18)
|-kflushd(2)
|-klogd(87)
|-kswapd(3)
|-login(160)---bash(192)---emacs(225)
|-lpd(121)
|-mingetty(161)
|-mingetty(162)
|-mingetty(163)
|-mingetty(164)
|-login(403)---bash(404)---pstree(594)
|-sendmail(134)
|-syslogd(78)
`-update(166)
另外系统中的所有的进程信息还存放在一个 task_struct 数据结构的双向链表中,根是 init 进程。这个表让 Linux 可以查到系统中的所有的进程。它需要这个表以提供对于 ps 或者 kill 等命令的支持。
Times and Timers 在一个进程的生命周期中,核心除了跟踪它使用的 CPU 时间还记录它的其他时间。每一个时间片( clock tick ),核心更新 jiffies 中当前进程在系统和用户态所花的时间综合。 Linux 也支持进程指定的时间间隔的计数器。进程可以使用系统调用建立计时器,在计时器到期的时候发送信号给自己。这种计时器可以是一次性的,也可是周期性的。
File system 进程可以根据需要打开或者关闭文件,进程的 task_struct 结构存放了每一个打开的文件描述符的指针和指向两个 VFS I 节点( inode )的指针。每一个 VFS I 节点唯一描述一个文件系统中的一个文件或目录,也提供了对于底层文件系统的通用接口。 Linux 下如何支持文件系统在第 9 章中描述。第一个 I 节点是该进程的根(它的主目录),第二个是它的当前或者说 pwd 目录。 Pwd 取自 Unix 命令:印出工作目录。这两个 VFS 节点本身有计数字段,随着一个或多个进程引用它们而增长。这就是为什么你不能删除一个进程设为工作目录的目录。
Virtual memory 多数进程都有一些虚拟内存(核心线程和核心守护进程没有), Linux 核心必须知道这些虚拟内存是如何映射到系统的物理内存中的。
Processor Specific Context 进程可以看作是系统当前状态的总和。只要进程运行,它就要使用处理器的寄存器、堆栈等等。当一个进程暂停的时候,这些进程的上下文、和 CPU 相关的上下文必须保存到进程的 task_struct 结构中。当调度者重新启动这个进程的时候,它的上下文就从这里恢复。
4.2 Identifiers (标识)
Linux ,象所有的 Unix ,使用用户和组标识符来检查对于系统中的文件和映像的访问权限。 Linux 系统中所有的文件都有所有权和许可,这些许可描述了系统对于该文件或目录拥有什么样的权限。基本的权限是读、写和执行,并分配了 3 组用户:文件属主、属于特定组的进程和系统中的其他进程。每一组用户都可以拥有不同的权限,例如一个文件可以让它的属主读写,它的组读,而系统中的其他进程不能访问。
Linux 使用组来给一组用户赋予对文件或者目录的权限,而不是对系统中的单个用户或者进程赋予权限。比如你可以为一个软件项目中的所有用户创建一个组,使得只有他们才能够读写项目的源代码。一个进程可以属于几个组(缺省是 32 个),这些组放在每一个进程的 task_struct 结构中的 groups 向量表中。只要进程所属的其中一个组对于一个文件有访问权限,则这个进程就又对于这个文件的适当的组权限。
一个进程的 task_struct 中有 4 对进程和组标识符。
Uid,gid 该进程运行中所使用的用户的标识符和组的标识符
Effective uid and gid 一些程序把执行进程的 uid 和 gid 改变为它们自己的(在 VFS I 节点执行映像的属性中)。这些程序叫做 setuid 程序。这种方式有用,因为它可以限制对于服务的访问,特别是那些用其他人的方式运行的,例如网络守护进程。有效的 uid 和 gid 来自 setuid 程序,而 uid 和 gid 仍旧是原来的。核心检查特权的时候检查有效 uid 和 gid 。
File system uid and gid 通常和有效 uid 和 gid 相等,检查对于文件系统的访问权限。用于通过 NFS 安装的文件系统。这时用户态的 NFS 需要象一个特殊进程一样访问文件。只有文件系统 uid 和 gid 改变(而非有效 uid 和 gid )。这避免了恶意用户向 NFS 的服务程序发送 Kill 信号。 Kill 用一个特别的有效 uid 和 gid 发送给进程。
Saved uid and gid 这是 POSI
【责编:admin】
--------------------next---------------------