您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > 第051章 进程管理及进程间通讯
第5章进程管理及进程间通讯本章介绍了Linux进程的管理、调度以及Linux系统支持的进程间通讯机制,并对某些通信手段的内部实现机制进行了分析。本章还讨论了Linux核心的一些基本任务和机制,将Linux内核中为使内核其他部分能有效工作的用于同步的几种机制集中起来分析,强调了它们之间在实现和使用上的不同。5.1Linux进程和线程一个大型的应用系统,往往需要众多进程协作。进程是操作系统理论的核心与基础,许多概念都和进程相关。进程的标准定义是:进程是可并发执行的程序在一个数据集合上的运行过程。换句话说,在自身的虚拟地址空间运行的一个单独的程序称作一个进程。在Linux系统中,当一个程序开始执行后,在开始执行到执行完毕退出这段时间里,它在内存中的部分就被称作一个进程。进程与程序是有区别的,程序只是一些预先设定好的代码和数据,进程是一个随时都可能发生变化的、动态的、使用系统运行资源的程序。程序是静态的,而进程是动态的。一个程序可以启动多个进程。和进程联系在一起的不仅有进程的指令和数据,而且还有当前的指令指针、所有的CPU寄存器以及用来保存临时数据的堆栈等,所有这些都随着程序指令的执行在变化。Linux操作系统包括三种不同类型的进程,每种类型的进程都有自己的特点和属性。(1)交互进程——由shell启动的进程。交互进程既可以在前台运行,也可以在后台运行。(2)批处理进程——这种进程和终端没有联系,是一个进程序列。(3)监控进程(也称守护进程)——Linux系统启动时启动的进程,并在后台运行。上述三种进程各有各的作用,使用场合也有所不同。5.1.1Linux进程管理的数据结构Linux是一个多任务的操作系统,在同一个时间内,可以有多个进程同时执行。由于单CPU计算机实际上在一个时间片断内只能执行一条指令,Linux使用了一种称为“进程调度(processscheduling)”的机制。首先为每个进程指派一定的运行时间,然后依照某种规则,从众多进程中挑选一个投入运行,其他的进程暂时等待,当正在运行的那个进程时间耗尽,或执行完毕退出,或因某种原因暂停,Linux就会重新进行调度,挑选下一个进程投入运行。因为每个进程占用的时间片都很短,在用户的角度看,就好像多个进程同时运行一样。进程在运行过程中,要使用许多计算机资源,例如CPU、内存、文件等。同时可能会有多个进程使用同一个资源,因此操作系统要跟踪所有的进程及其所使用的系统资源,以便能够管理进程和资源。在Linux中,每个进程在创建时都会被分配一个数据结构,称为进程控制块(ProcessControlBlock,PCB)。PCB中包含了很多重要的信息,供系统调度和进程本身执行使用,其中最重要的是进程ID(processID,PID),进程ID也被称作进程标识符,是一个非负的整数,在Linux操作系统中唯一地标志一个进程。在最常使用的i386架构(即PC使用的架构)上,PID的变化范围是一个非负整数0-32767,这也是所有可能取到的进程ID。每个进程的进程ID各不相同。可使用ps命令看看当前系统中有多少进程在运行。除标题外,每一行都代表一个进程。在各列中,PID一列代表了各进程的进程ID,command一列代表了进程的名称或在shell中调用的命令行。Linux中的每个进程有自己的虚拟地址空间,操作系统的一个最重要的基本管理目的,就是避免进程之间的互相影响。但有时用户也希望能够利用两个或多个进程的功能完成同一任务,为此,Linux提供许多机制,利用这些机制,进程之间可以进行通讯并共同完成某项任务,这种机制称为“进程间通讯(InterprocessCommunication,IPC)”。信号和管道是常见的两种IPC机制,但Linux也提供其他IPC机制。一般来说,Linux下的进程包含以下几个关键要素:有一段可执行程序;有专用的系统堆栈空间;内核中有它的控制块(进程控制块),描述进程所占用的资源,这样,进程才能接受内核的调度;具有独立的存储空间。Linux内核利用一个数据结构task_struct来代表一个进程,代表进程的数据结构指针形成了一个task数组(在Linux中,任务和进程是两个相同的术语),这种指针数组有时也成为指针向量。这个数组的大小默认为512,表明在Linux系统中能够同时运行的进程最多可有512。当建立新进程的时候,Linux为新的进程分配一个task_struct结构,然后将指针保存在task数组中。task_struct结构中包含了许多字段,按照字段功能,可分成如下几类:(1)标识号。系统通过进程标识号唯一识别一个进程,但进程标识号并不是进程对应的task_struct结构指针在task数组中的索引号。另外,一个进程还有自己的用户和组标识号,系统通过这两个标识号判断进程对文件或设备的访问权。(2)状态信息。一个Linux进程可有如下几种状态:运行、等待、停止和僵死。(3)调度信息。调度程序利用该信息完成进程之间的切换。(4)有关进程间通讯的信息。系统利用这一信息实现进程间的通讯。(5)进程链信息。在Linux系统中,除初始化进程之外,任何一个进程都具有父进程。每个进程都是从父进程中“克隆”出来的。进程链则包含进程的父进程指针、和该进程具有相同父进程的兄弟进程指针以及进程的子进程指针。另外,Linux利用一个双向链表记录系统中所有的进程,这个双向链表的根就是init进程。利用这个链表中的信息,内核可以很容易地找到某个进程。(6)时间和定时器。系统在这些字段中保存进程的建立时间,以及在其生命周期中所花费的CPU时间,这两个时间均以jiffies为单位。该时间由两部分组成,一是进程在用户模式下花费的时间,二是进程在系统模式下花的时间。Linux也支持和进程相关的定时器,应用程序可通过系统调用建立定时器,当定时器到期,操作系统会向该进程发送sigalrm信号。(7)文件系统信息。进程可以打开文件系统中的文件,系统需要对这些文件进行跟踪。系统使用这类字段记录进程所打开的文件描述符信息。另外,还包含指向虚拟文件系统(VirtualFileSystems,VFS)两个索引节点的指针,这两个索引节点分别是进程的主目录以及进程的当前目录。索引节点中有一个引用计数器,当有新的进程指向某个索引节点时,该索引节点的引用计数器会增加计数。未被引用的索引节点的引用计数为0,因此,当包含在某个目录中的文件正在运行时,就无法删除这一目录,因为这一目录的引用计数大于0。(8)和进程相关的上下文信息。如前所述,进程可被看成是系统状态的集合,随着进程的运行,这一集合发生变化。进程上下文就是用来保存系统状态的task_struct字段。当调度程序将某个进程从运行状态切换到暂停状态时,会在上下文中保存当前的进程运行环境,包括CPU寄存器的值以及堆栈信息;当调度程序再次选择该进程运行时,则会从进程上下文信息中恢复进程的运行环境。5.1.2标识符信息和所有的Unix系统一样,Linux使用用户标识符和组标识符判断用户对文件和目录的访问许可。Linux系统中的所有文件或目录均具有所有者和许可属性,Linux据此判断某个用户对文件的访问权限。对一个进程而言,系统在task_struct结构中记录如表5.1所示的4对标识符。uid和gid运行进程所代表的用户之用户标识号和组标识号,通常就是执行该进程的用户。有效uid和gid某些程序可以将uid和gid改变为自己私有的uid和gid。系统在运行这样的程序时,会根据修改后的uid及gid判断程序的特权,例如,是否能够直接进行I/O输出等。通过setuid系统调用,可将程序的有效uid和gid设置为其他用户。在该程序映像文件的VFS索引节点中,有效uid和gid由索引节点的属性描述。文件系统uid和gid这两个标识符和上述标识符类似,但用于检查对文件系统的访问许可时。处于用户模式的NFS服务器作为特殊进程访问文件时使用这两个标识符。保存uid和gid如果进程通过系统调用修改了进程的uid和gid,这两个标识符则保存实际的uid和gid。5.1.3进程状态信息Linux中的进程有4种状态,如表5.2所示。运行状态该进程是当前正在运行的进程;或者,该进程是可以运行的进程,即正在等待调度程序将CPU分配给它。等待状态进程正在等待某个事件或某个资源。这种进程又分为可中断的进程和不可中断的进程两种。可中断的等待进程可被信号中断,而不可中断的等待进程是正在直接等待硬件状态条件的进程,在任何情况下都不能被中断。停止状态进程处于停止状态,通常由于接收到信号而停止,例如,进程在接收到调试信号时处于停止状态。僵死状态进程已终止,但在task数组中仍占据着一个task_struct结构。顾名思义,处于这种状态的进程实际是死进程。5.1.4文件信息如图5.1所示,系统中的每个进程有两个数据结构用于描述进程与文件相关的信息。其中,fs_struct描述了上面提到的指向VFS两个索引节点的指针,即root和pwd。另外,这个结构还包含一个umask字段,它是进程创建文件时使用的默认模式,可通过系统调用修改这一默认模式。另一个结构为files_struct,它描述了当前进程所使用的所有文件信息。从图中可以看出,每个进程能够同时拥有256个打开的文件,fs[0]到fs[255]就是指向这些file结构的指针。文件的描述符实际就是fs指针数组的索引号。task_struct……fsfiles……fs_structcountumask*root*pwdfiles_structcountclose_on_execopen_fsfd[0]fd[1]……fd[255]inodeinodef_modefilef_posf_flagsf_countf_ownerf_inodef_opf_versioninode文件操作例程集图5.1进程的文件信息在file结构中,f_mode是文件的打开模式,只读、只写或读写;f_pos是文件的当前位置;f_inode指向VFS中该文件的索引节点;f_op包含了对该文件的操作例程集。利用f_op,可以针对不同的文件定义不同的操作函数,例如一个用来向文件中写数据的函数。Linux利用这一抽象机制,实现了管道这一进程间通讯机制。这种抽象方法在Linux内核中很常见,通过这种方法,可使特定的内核对象具有类似C++对象的多态性。Linux进程启动时,有三个文件描述符被打开,它们是标准输入、标准输出和错误输出,分别对应fs数组的三个索引,即0、1和2。如果启动时进行输入输出重定向,则这些文件描述符指向指定的文件而不是标准的终端输入/输出。每当进程打开一个文件时,就会利用files_struct的一个空闲file指针指向打开的文件描述结构file。对文件的访问通过file结构中定义的文件操作例程和虚拟文件系统(VirtualFileSystem,VFS)的索引节点信息来完成。5.1.5虚拟内存进程的虚拟内存包含了进程所有的可执行代码和数据。运行某个程序时,系统要根据可执行映像中的信息,为进程代码和数据分配虚拟内存;进程在运行过程中,可能会通过系统调用动态申请虚拟内存或释放已分配的内存,新分配的虚拟内存必须和进程已有的虚拟地址链接起来才能使用。Linux进程可以使用共享的程序库代码或数据,因此,共享库的代码和数据也需要链接到进程已有的虚拟地址中。Linux系统利用了需求分页机制来避免对物理内存的过分使用。因为进程可能会访问当前不在物理内存中的虚拟内存,这时操作系统将通过对处理器的页故障处理装入内存页。系统为此需要修改进程的页表,以便标志虚拟页是否在物理内存中,同时,Linux还需要知道进程地址空间中任何一个虚拟地址区域的来源和当前所在位置,以便能够装入物理内存。……task_structmm……countmm_structpgdmmap_sem……mmapmmap_avlcountvm_flagsvm_endvm_area_structvm_startvm_inode
本文标题:第051章 进程管理及进程间通讯
链接地址:https://www.777doc.com/doc-3208920 .html