那啥,虽然ELF完了,但核心创作过程的核心部分人员有新工作了吗

显示空闲内存页面的平均数量.系統为内存页面建立了一个缓冲区,称为空闲列表.当 VMM(虚拟内存管理)需要空间时可以立即访问此空闲列表.VMM在空闲列表中保存最少页面的数量决定於minfree参数,该参数执行 vmtune 命令加f参数可以得到. ### re ### 表示系统回收的内存页面数.在AIX 5L当中不再支持回收,因为它只能提供有限的系统性能的信息却无法弥补哏踪回收算法对系统的负面影响 ### pi ### 表示分页空间调入数量的详细信息.分页空间是驻留在磁盘上的虚拟内存的一部分.当内存过量使用时,它用作超出部分的内存. ### po ### 显示页面调出数量的详细情况. ### fr ### 在一定时间间隔内为填充内存空闲表或分配给某进程所需要释放的内存页面. ### sr ### 为得到fr数量的空閑页面所需要检查的页面数.当fr和sr的比例(fr:sr)很高时,内存将会过量使用.fr:sr 为 1:4 的比例意味着每释放一页,有四页被检查了.当 po*SYS > fr (SYS 为一系统参数,可用命令/usr/samples/kernel/schedtune查看)時,系统自身认为已到崩溃边缘.该值在有128MB或更多内存的系统上默认值为0,表示禁止内存加载控制,否则默认值为6.系统崩溃表明此时系统使用大量時间用于内存换入/换出,而没有足够时间处理应用或正常工作.这时一些进程将被临时挂起或被kill掉,系统运行明显减慢. ### cy ### rw,log=/dev/hd8 ***** 创建文件系统流程end ***** 为设备增加一个外接磁盘start 先将设备下电,连接硬盘,重启即可,系统会自动分配一个物理卷名给新磁盘hdisk(n),n是下一个磁盘号.如果内置磁盘的卷标是hdisk0那么新加 磁盘就会取名为hdisk1.这时硬盘只是对LVM来说可用,但尚未配置.配置磁盘可使用SMIT或者chdev命令实现. ->命令为: reorgvg //导入卷组 #smit importvg //若用户要把当前系统中的卷组转移到其它系统中,以下为操作步骤: //1:必须使用exportvg或者smit工具把卷组从当前系统导出, 用importvg或者smit工具把卷组信息导入到目的设备系统中; //2:导出前必须是非激活状態, 卷组被导出, 系统将删除此卷组的所有信息; 指示磁盘的设备名;-a: 指定设备属性值 注意:该命令对于已设置为物理卷的磁盘没有作用 3、修改物理卷特性 (1) 给物理卷设置分配许可权 物理卷的分配许可权决定那些物理卷可以分配给逻辑卷,那些不可以. 以下命令关闭hdisk1的分配许可: #chpv -a n hdisk1 以下命令打开汾配许可: #chpv -a y hdisk1 (2) 设置物理卷的可用性 可用性决定了是否可以处理逻辑输入/输出操作, 当一个物理卷从系统中移除或者故障导致不可用时, 应将其置为鈈可用: #chpv -v r pvname 该操作将会冻结该物理卷中所有的VGDA和VGSA拷贝,将来卷组激活时将不会被加入卷组,同样该卷的信息也从该卷组中其他的物理卷 的VGDA和VGSA中删除. 置为可用: #chpv -v a pvname 注意: 后跟y,n,s y:严格分配策略,逻辑分区的拷贝不共享相同的物理卷,此为缺省值; n:不设置严格分配策略,逻辑分区的拷贝可共享相同的物理卷; s:超级严格分配策略,一个为镜像分配的分区不能和另一个镜像的分区共享相同的物理卷; ##创建卷组vg03, 大小为15个LP, 这15个LP分别从磁盘hdisk5、hdisk6、hdisk9上选择 mklv vg03 15 hdisk5


VIP专享文档是百度文库认证用户/机構上传的专业性文档文库VIP用户或购买VIP专享文档下载特权礼包的其他会员用户可用VIP专享文档下载特权免费下载VIP专享文档。只要带有以下“VIP專享文档”标识的文档便是该类文档

VIP免费文档是特定的一类共享文档,会员用户可以免费随意获取非会员用户需要消耗下载券/积分获取。只要带有以下“VIP免费文档”标识的文档便是该类文档

VIP专享8折文档是特定的一类付费文档,会员用户可以通过设定价的8折获取非会員用户需要原价获取。只要带有以下“VIP专享8折优惠”标识的文档便是该类文档

付费文档是百度文库认证用户/机构上传的专业性文档,需偠文库用户支付人民币获取具体价格由上传人自由设定。只要带有以下“付费文档”标识的文档便是该类文档

共享文档是百度文库用戶免费上传的可与其他用户免费共享的文档,具体共享方式由上传人自由设定只要带有以下“共享文档”标识的文档便是该类文档。

还剩4页未读 继续阅读

    本章描述进程是什么以及 Linux 如何创建、管理和删除系统中的进程
    进程执行操作系统中的任务。程序是存放在磁盘上的包括一系列机器代码指令
和数据的可执行的映像因此,是一个被动的实体进程可以看作是一个执行中的
计算机程序。它是动态的实体在处理器执行机器代码指令时不断改变。处理程序
嘚指令和数据进程也包括程序计数器和其他 CPU 的寄存器以及包括临时数据(
例如例程参数、返回地址和保存的变量)的堆栈。当前执行的程序或者说进程,
包括微处理器中所有的当前的活动 Linux 是一个多进程的操作系统。进程是分
离的任务拥有各自的权利和责任。如果一個进程崩溃它不应该让系统中的另一
个进程崩溃。每一个独立的进程运行在自己的虚拟地址空间除了通过安全的核心
管理的机制之外無法影响其他的进程。
    在一个进程的生命周期中它会使用许多系统资源它会用系统的 CPU 执行它


的指令,用系统的物理内存来存储它和它的數据它会打开和使用文件系统中的文
件,会直接或者间接使用系统的物理设备 Linux 必须跟踪进程本身和它使用的
系统资源以便管理公平地管理该进程和系统中的其他进程。如果一个进程独占了系
统的大部分物理内存和 CPU 对于其他进程就是不公平的。
操作系统它的目标是让進程一直在系统的每一个 CPU 上运行,充分利用 CPU
如果进程数多于 CPU (多数是这样),其余的进程必须等到 CPU 被释放才能运行
多进程是一个简单嘚思想:一个进程一直运行,直到它必须等待通常是等待一
些系统资源,等拥有了资源它才可以继续运行。在一个单进程的系统比洳 DOS
 , CPU 被简单地设为空闲这样等待的时间就会被浪费。在一个多进程的系统中
同一时刻许多进程在内存中。当一个进程必须等待时操作系统将 CPU 从这个进
程拿走并将它交给另一个更需要的进程。是调度程序选择了
    下一次最合适的进程 Linux 使用了一系列的调度方案来保证公平。
Linux 必须透明地管理这些文件,因为进程使用系统的共享的库


 互用)的数据结构来表示,用来管理系统中的进程 Task 向量表是指向系统中
烸一个 task_struct 数据结构的指针的数组。这意味着系统中最大进程数受 task
 向量表的限制缺省是 512 。当新的进程创建的时候从系统内存中分配一个新
    除了普通进程, Linux 也支持实时进程这些进程必须对于外界事件迅速反
应(因此叫做“实时”),调度程序必须和普通用户进程区分对待雖然
task_struct 数据结构十分巨大、复杂,但是它的域可以分为以下的功能:
:(这里漏掉了 SWAPPING 因为看来没用到)
统的一个 CPU 上)
程可以被信号中断,洏不可中断的等待进程直接等待硬件条件不能被任何情况中


    Stopped 进程停止了,通常是接收到了一个信号正在调试的进程可以在停止
task_struct 数据结構的条目。就想听起来一样是一个死亡的进程。
task 向量表中的索引而只是一个数字。每一个进程也都有用户和组( user and
 group )的标识符用来控淛进程对于系统中文件和设备的访问。
管道和信号灯( semaphores )也支持系统 V 的 IPC 机制,即共享内存、信号
灯和消息队列关于 Linux 支持的 IPC 机制在第 5 章Φ描述。
每一个进程除了初始的进程之外,都有一个父进程新进程不是创建的,而是拷
贝或者说从前一个进程克隆的( cloned )。每一个進程的 task_struct 中都
有指向它的父进程和兄弟进程(拥有相同的父进程的进程)以及它的子进程的的指


当前进程在系统和用户态所花的时间综合 Linux 吔支持进程指定的时间间隔的
计数器。进程可以使用系统调用建立计时器在计时器到期的时候发送信号给自己
。这种计时器可以是一次性的也可是周期性的。
构存放了每一个打开的文件描述符的指针和指向两个 VFS I 节点( inode )的指
针每一个 VFS I 节点唯一描述一个文件系统中的一個文件或目录,也提供了对
于底层文件系统的通用接口 Linux 下如何支持文件系统在第 9 章中描述。第一
个 I 节点是该进程的根(它的主目录)苐二个是它的当前或者说 pwd 目录。
Pwd 取自 Unix 命令:印出工作目录这两个 VFS 节点本身有计数字段,随着一
个或多个进程引用它们而增长这就是为什么你不能删除一个进程设为工作目录的
), Linux 核心必须知道这些虚拟内存是如何映射到系统的物理内存中的
程运行,它就要使用处理器嘚寄存器、堆栈等等当一个进程暂停的时候,这些进
程的上下文、和 CPU 相关的上下文必须保存到进程的 task_struct 结构中当调
度者重新启动这个进程的时候,它的上下文就从这里恢复


像的访问权限。 Linux 系统中所有的文件都有所有权和许可这些许可描述了系
统对于该文件或目录拥有什么样的权限。基本的权限是读、写和执行并分配了 3
 组用户:文件属主、属于特定组的进程和系统中的其他进程。每一组用户都可以
拥囿不同的权限例如一个文件可以让它的属主读写,它的组读而系统中的其他
    Linux 使用组来给一组用户赋予对文件或者目录的权限,而不是對系统中的单
个用户或者进程赋予权限比如你可以为一个软件项目中的所有用户创建一个组,
使得只有他们才能够读写项目的源代码┅个进程可以属于几个组(缺省是 32 个
),这些组放在每一个进程的 task_struct 结构中的 groups 向量表中只要进
程所属的其中一个组对于一个文件有访问权限,则这个进程就又对于这个文件的适
Uid,gid 该进程运行中所使用的用户的标识符和组的标识符
的(在 VFS I 节点执行映像的属性中)这些程序叫做 setuid 程序。这种方式
有用因为它可以限制对于服务的访问,特别是那些用其他人的方式运行的例如


来的。核心检查特权的时候检查有效 uid 和 gid
的访问权限。用于通过 NFS 安装的文件系统这时用户态的 NFS 服务器需要象一
个特殊进程一样访问文件。只有文件系统 uid 和 gid 改变(而非有效 uid 和
gid )这避免了恶意用户向 NFS 的服务程序发送 Kill 信号。 Kill 用一个特
别的有效 uid 和 gid 发送给进程
    所有的进程部分运行与用户态,部分运行于系统态底层嘚硬件如何支持这些
状态各不相同但是通常有一个安全机制从用户态转入系统态并转回来。用户态比系
统态的权限低了很多每一次进程執行一个系统调用,它都从用户态切换到系统态
并继续执行这时让核心执行这个进程。 Linux 中进程不是互相争夺成为当前
运行的进程,它們无法停止正在运行的其它进程然后执行自身每一个进程在它必
须等待一些系统事件的时候会放弃 CPU 。例如一个进程可能不得不等待从┅个
文件中读取一个字符。这个等待发生在系统态的系统调用中进程使用了库函数打


开并读文件,库函数又执行系统调用从打开的文件Φ读入字节这时,等候的进程
会被挂起另一个更加值得的进程将会被选择执行。进程经常调用系统调用所以
经常需要等待。即使进程执行到需要等待也有可能会用去不均衡的 CPU 事件所
以 Linux 使用抢先式的调度。用这种方案每一个进程允许运行少量一段时间,
 200 毫秒当这個时间过去,选择另一个进程运行原来的进程等待一段时间直
到它又重新运行。这个时间段叫做时间片
    需要调度程序选择系统中所有鈳以运行的进程中最值得的进程。一个可以运行
的进程是一个只等待 CPU 的进程 Linux 使用合理而简单的基于优先级的调度算
法在系统当前的进程Φ进行选择。当它选择了准备运行的新进程它就保存当前进
程的状态、和处理器相关的寄存器和其他需要保存的上下文信息到进程的
task_struct 数據结构中。然后恢复要运行的新的进程的状态(又和处理器相关)
把系统的控制交给这个进程。为了公平地在系统中所有可以运行( runnable )
嘚进程之间分配 CPU 时间调度程序在每一个进程的 task_struct 结构中保存了
比所有其它进程的优先级高。如果有一个实时的进程准备运行那么它总是先被运
out )。在环的调度策略下每一个实时进程依次运行,而在先进先出的策略下


每一个可以运行的进程按照它在调度队列中的顺序运荇,这个顺序不会改变
jiffies )。你可以通过系统调用或者 renice 命令来改变一个进程的优先级
更高的优先级。这个域允许调度程序赋予每一个实時进程一个相对的优先级实时
进程的优先级可以用系统调用来修改
先级( priority ),每一次时钟周期递减
    调度程序从核心的多个地方运行。咜可以在把当前进程放到等待队列之后运行
也可以在系统调用之后进程从系统态返回进程态之前运行。需要运行调度程序的
另一个原因昰系统时钟刚好把当前进程的计数器 (counter) 置成了 0 每一次调
度程序运行它做以下工作:
这些轻量级的核心线程在第 11 章详细描述


Current pocess 在选择另一个进程之前必须处理当前进程。
如果当前进程的调度策略是环则它放到运行队列的最后
如果任务是可中断的而且它上次调度的时候收到过一個信号,它的状态变为
如果当前进程超时它的状态成为 RUNNING
如果当前进程的状态为 RUNNING 则保持此状态
程序查找最值得运行的进程时不会考虑这样嘚进程。
如果有实时的进程(具有实时调度策略),就会比普通进程更重一些普通进程
果系统中存在可运行的实时进程,就总是在任哬普通可运行的进程之前运行当前
的进程,因为用掉了一些时间片(它的 counter 减少了)所以如果系统中由其
他同等优先级的进程,就会处於不利的位置:这也是应该的如果几个进程又同样
的优先级,最接近运行队列前段的那个就被选中当前进程被放到运行队列的后面


。洳果一个平衡的系统拥有大量相同优先级的进程,那么回按照顺序执行这些进
程这叫做环型调度策略。不过因为进程需要等待资源,它们的运行顺序可能会
运行新的进程。当一个进程运行的时候它使用了 CPU 和系统的寄存器和物理内
存每一次它调用例程都通过寄存器戓者堆栈传递参数、保存数值比如调用例程的
返回地址等。因此当调度程序运行的时候它在当前进程的上下文运行。它可能是
特权模式:核心态但是它仍旧是当前运行的进程。当这个进程要挂起时它的所
有机器状态,包括程序计数器 (PC) 和所有的处理器寄存器必须存到進程的
task_struct 数据结构中。然后必须加载新进程的所有机器状态。这种操作依赖
于系统不同的 CPU 不会完全相同地实现,不过经常都是通过一些硬件的帮助
    交换出去进程的上下文发生在调度的最后。前一个进程存储的上下文就是当
这个进程在调度结束的时候系统的硬件上下文嘚快照。相同的当加载新的进程的
上下文时,仍旧是调度结束时的快照包括进程的程序计数器和寄存器的内容。
    如果前一个进程或者噺的当前进程使用虚拟内存则系统的页表需要更新。同
 Look-aside Table )或者缓存的页表条目必须清除属于前一个进程的缓存的页


成为一个 SMP (对称多處理)的操作系统。这就是可以在系统中的 CPU 之间平
衡负载的能力。负载均衡没有比在调度程序中更重要的了
    在一个多处理器的系统中,希望的情况是:所有的处理器都繁忙地运行进程
每一个进程都独立地运行调度程序直到它的当前的进程用完时间片或者不得不等待
系統资源。 SMP 系统中第一个需要注意的是系统中可能不止一个空闲( idle )
进程在一个单处理器的系统中,空闲进程是 task 向量表中的第一个任务茬一
个 SMP 系统中,每一个 CPU 都有一个空闲的进程而你可能有不止一个空闲 CPU
 。另外每一个 CPU 有一个当前进程,所以 SMP 系统必须记录每一个处理器嘚
进程每一次被选择运行时不要在不同的 CPU 上运行是没什么道理的但是
位,则该进程可以运行在处理器 N 上当调度程序选择运行的进程的時候,它不
会考虑 processor_mask 相应位没有设置的进程调度程序也会利用上一次在当前
处理器运行的进程,因为把进程转移到另一个处理器上经常会囿性能上的开支


    图 4.1 显示了描述系统每一个进程中的用于描述和文件系统相关的信息的两
 Umask 是新文件创建时候的缺省模式,可以通过系统调鼡改变
程序从标准输入读取,向标准输出写错误信息输出到标准错误。这些可以是文件
终端输入 / 输出或者世纪的设备,但是从程序嘚角度它们都被看作是文件每
每一个描述进程形用的文件。 F_mode 域描述了文件创建的模式:只读、读写或者
只写 F_pos 记录了下一次读写操作在攵件中的位置。 F_inode 指向描述该文件
的 I 节点 f_ops 是指向一组例程地址的指针,每一个地址都是一个用于处理文
件的函数例如写数据的函数。这種抽象的接口非常强大使得 Linux 可以支持
大量的文件类型。我们可以看到在 Linux 中 pipe 也是用这种机制实现的。


这个新的 file 结构 Linux 进程启动时有 3 个文件描述符已经打开。这就是标
准输入、标准输出和标准错误这都是从创建它们的父进程中继承过来的。对于文
件的访问都是通过标准的系统调用需要传递或返回文件描述符。这些描述符是进
程的 fd 向量表中的索引所以标准输入、标准输出和标准错误的文件描述符分别
是 0 , 1 和 2 对于文件的所有访问都是利用 file 数据结构中的文件操作例
程和它的 VFS I 节点一起来实现的。
    进程的虚拟内存包括多种来源的执行代码和数據第一种是加载的程序映像,
例如 ls 命令这个命令,象所有的执行映像一样由执行代码和数据组成。映像
文件中包括将执行代码和相關的程序数据加载到进程地虚拟内存中所需要的所有信
息第二种,进程可以在处理过程中分配(虚拟)内存比如用于存放它读入的文
件的内容。新分配的虚拟内存需要连接到进程现存的虚拟内存中才能使用第三中
, Linux 进程使用通用代码组成的库例如文件处理。每一个進程都包括库的一
份拷贝没有意义 Linux 使用共享库,几个同时运行的进程可以共用这些共享
库里边的代码和数据必须连接到该进程的虚拟哋址空间和其他共享该库的进程的虚
    在一个特定的时间,进程不会使用它的虚拟内存中包括的所有代码和数据它
可能包括旨在特定情况丅使用的代码,比如初始化或者处理特定的事件它可能只


是用了它的共享库中一部分例程。如果把所有这些代码都加载到物理内存中而鈈使
用只会是浪费把这种浪费和系统中的进程数目相乘,系统的运行效率会很低
Linux 改为使用 demand paging 技术,进程的虚拟内存只在进程试图使用的時候
才调入物理内存中所以, Linux 不把代码和数据直接加载到内存中而修改进
程的页表,把这些虚拟区域标志为存在但是不在内存中当進程试图访问这些代码
或者数据,系统硬件会产生一个 page fault 把控制传递给 Linux 核心处理。
因此对于进程地址空间的每一个虚拟内存区域, Linux 需要矗到它从哪里来和
如何把它放到内存中这样才可以处理这些 page fault 。
    Linux 核心需要管理所有的这些虚拟内存区域每一个进程的虚拟内存的内容
进程的 mm_struct 数据结构也包括加载的执行映像的信息和进程页表的指针。它
包括了指向一组 vm_area_struct 数据结构的指针每一个都表示该进程中的一个
    这个链接表按照虚拟内存顺序排序。图 4.2 显示了一个简单进程的虚拟内存
分布和管理它的核心数据结构因为这些虚拟内存区域来源不同, Linux 通过
vm_area_struct 指姠一组虚拟内存处理例程(通过 vm_ops )的方式抽象了接口
这样进程的所有虚拟内存都可以用一种一致的方式处理,不管底层管理这块内存
的垺务如何不同例如,会有一个通用的例程在进程试图访问不存在的内存时调


    当 Linux 为一个进程创建新的虚拟内存区域和处理对于不在系统粅理内存中
的虚拟内存的引用时,反复引用进程的 vm_area_struct 数据结构列表这意味着
它查找正确的 vm_area_struct 数据结构所花的事件对于系统的性能十分重要。為
右指针左指针指向拥有较低起始虚拟地址的节点,右指针指向一个拥有较高起始
虚拟地址的节点为了找到正确的节点, Linux 从树的根开始跟从每一个节点
的左和右指针,直到找到正确的 vm_area_struct 当然,在这个树中间释放不需
要时间而插入新的 vm_area_struct 需要额外的处理时间。
    当一个进程分配虚拟内存的时候 Linux 并不为该进程保留物理内存。它通
过一个新的 vm_area_struct 数据结构来描述这块虚拟内存连接到进程的虚拟内
存列表中。当進程试图写这个新的虚拟内存区域的时候系统会发生 page
fault 。处理器试图解码这个虚拟地址但是没有对应该内存的页表条目,它会放
拟地址昰不是在进程的虚拟地址空间 如果是, Linux 创建适当的 PTE 并为该
进程分配物理内存页也许需要从文件系统或者交换磁盘中加载相应的代码或鍺数
据,然后进程从引起 page fault 的指令重新运行因为这次该内存实际存在,可


    当系统启动的时候它运行在核心态这时,只有一个进程:初始囮进程象所
有其他进程一样,初始进程有一组用堆栈、寄存器等等表示的机器状态当系统中
的其他进程创建和运行的时候这些信息存茬初始进程的 task_struct 数据结构中
。在系统初始化结束的时候初始进程启动一个核心线程(叫做 init )然后执行
空闲循环,什么也不做当没有什么鈳以做的时候,调度程序会运行这个空闲的进
程这个空闲进程的 task_struct 是唯一一个不是动态分配而是在核心连接的时
候静态定义的,为了不至於混淆叫做 init_task 。
    Init 核心线程或进程拥有进程标识符 1 是系统的第一个真正的进程。它执
行系统的一些初始化的设置(比如打开系统控制它咹装根文件系统),然后执行
的新进程这些新进程自身可能创建新的进程。例如: getty 进程可能会在用户
试图登录的时候创建一个 login 的进程系统中的所有进程都是 init 核心线程
    新的进程的创建是通过克隆旧的进程,或者说克隆当前的进程来实现的一个
新的任务是通过系统调用创建的( fork 或 clone ),克隆发生在核心的核心态
在系统调用的最后,产生一个新的进程等待调度程序选择它运行。从系统的物


理内存中为这个克隆进程的堆栈(用户和核心)分配一个或多个物理的页用于新的
 task_struct 数据结构一个进程标识符将会创建,在系统的进程标识符组中是
唯一嘚但是,也可能克隆的进程保留它的父进程的进程标识符新的
    克隆进程的时候, Linux 允许两个进程共享资源而不是拥有不同的拷贝包
括進程的文件,信号处理和虚拟内存共享这些资源的时候,它们相应的 count
字段相应增减这样 Linux 不会释放这些资源直到两个进程都停止使用。唎如
如果克隆的进程要共享虚拟内存,它的 task_struct 会包括一个指向原来进程的
据结构、相应的 mm_struct 数据结构和克隆进程的页表这时没有拷贝进程嘚虚
拟内存。这会是困难和耗时的任务因为一部分虚拟内存可能在物理内存中而另一
部分可能在交换文件中。替代底 Linux 使用了叫做“ copy on write ”嘚技术
,即只有两个进程中的一个试图写的时候才拷贝虚拟内存任何不写入的虚拟内存
,甚至可能写的都可以在两个进程之间共享二蔀会有什么害处。只读的内存例
如执行代码,可以共享为了实现“ copy on write ”,可写的区域的页表条目


当一个进程试图写向着这个虚拟内存嘚时候会产生 page fault 。这时 Linux
将会制作这块内存的一份拷贝并处理两个进程的页表和虚拟内存的数据结构
    核心跟踪进程的 CPU 时间和其他一些时间。烸一个时钟周期核心更新当前
进程的 jiffies 来表示在系统和用户态下花费的时间总和。
timer )进程可以使用这些计时器在这些计时器到期的时候發送给自身信号。支
Real 这个计时器使用实时计时当计时器到期,发送给进程一个 SIGALRM 信号
Virtual 这个计时器只在进程运行的时候计时,到期的时候发送给进程一个


Profile 在进程运行的时候和系统代表进程执行的时候都及时。到期的时候会发
构中记录所有的必要信息。可以使用系统调用建立这些间隔计时器启动、停止它
们,读取当前的数值虚拟和 profile 计时器的处理方式相同:每一次时钟周期
,当前进程的计时器递减如果到期,就发出适当的信号
个进程都有自己的 timer_list 数据结构当时使用实时计时器的时候,使用系统
的 timer 表当它到期的时候,计时器后半部分處理把它从队列中删除并调用间
隔计时器处理程序它产生 SIGALRM 信号并重启动间隔计时器,把它加回到系统
释程序是和其他进程一样的用户进程叫做 shell (想象一个坚果,把核心作为


中间可食的部分而 shell 包围着它,提供一个接口) Linux 中有许多 shell
pwd ,命令是可执行的二进制文件对于输叺的每一个命令, shell 在当前进程
的搜索路径指定的目录中(放在 PATH 环境变量)查找匹配的名字如果找到了文
件,就加载并运行 Shell 用上述的 fork 机淛克隆自身,并在子进程中用找到
的执行映像文件的内容替换它正在执行的二进制映像( shell )通常 shell 等
待命令结束,或者说子进程退出你鈳以通过输入 control-Z 发送一个
SIGSTOP 信号给子进程,把子进程停止并放到后台让 shell 重新运行。你可以
并重新运行它会持续运行直到它结束或者需要从終端输入或输出。
文件必须用合适的解释程序识别并运行例如 /bin/sh 解释 shell script 。可
执行的目标文件包括了执行代码和数据以及足够的其他信息时嘚操作系统可以把
它们加载到内存中并执行。 Linux 中最常用的目标文件类型是 ELF 而理论上,
 Linux 灵活到足以处理几乎所有的目标文件格式
    好像文件系统一样, Linux 可以支持的二进制格式也是在核心连接的时候直
接建立在核心的或者是可以作为模块加载的核心保存了支持的二进制格式(见图
 4.3 )的列表,当试图执行一个文件的时候每一个二进制格式都被尝试,直到


可以工作通常, Linux 支持的二进制文件是 a.out 和 ELF 可执行文件鈈需
要完全读入内存,而使用叫做 demand loading 的技术当进程使用执行映像的一
部分的时候它才被调入内存,未被使用的映像可以从内存中废弃
Unix 系統实验室设计,现在成为 Linux 最常用的格式虽然和其他目标文件格式
行文件包括可执行代码(有时叫做 text )和数据( data )。执行映像中的表描
述叻程序应该如何放到进程的虚拟内存中静态连接的映像是用连接程序( ld )
或者连接编辑器创建的,单一的映像中包括了运行该映像所需偠的所有的代码和数
据这个映像也描述了该映像在内存中的布局和要执行的第一部分代码在映像中的


打印“ hello world ”然后退出。头文件描述了咜是一个 ELF 映像有两个物理
个物理头描述映像中的执行代码,在虚拟地址 0x8048000 有 65532 字节。因为
它是静态连接的所以包括输出“ hello world ”的调用 printf ()嘚所有的
库代码。映像的入口即程序的第一条指令,不是位于映像的起始位置而在虚拟
地址 0x8048090 ( e_entry )。代码紧接着在第二物理头后面开始这个物理头
描述了程序的数据,将会加载到虚拟内存地址 0x8059BB8 这块数据可以读写。
你会注意到文件中数据的大小是 2200 字节( p_filesz )而在内存中的夶小是
4248 字节因为前 2200 字节包括预先初始化的数据,而接着的 2048 字节包括
会被执行代码初始化的数据
的加载映像。它设置虚拟内存数据结构即进程的 vm_area_struct 和它的页表。
当程序执行了 page fault 的时候程序的代码和数据会被放到物理内存中。没有
用到的程序部分将不会被放到内存中一旦 ELF ②进制格式加载程序满足条件,
映像是一个有效的 ELF 可执行映像它把进程的当前可执行映像从它的虚拟内存
中清除。因为这个进程是个克隆的映像(所有的进程都是)旧的映像是父进程执
行的程序的映像(例如命令解释程序 shell bash )。清除旧的可执行映像会废弃
旧的虚拟内存的數据结构重置进程的页表。它也会清除设置的其他信号处理程序
关闭打开的文件。在清除过程的最后进程准备运行新的可执行映像。不管可执


行映像的格式如何进程的 mm_struct 中都要设置相同的信息。包括指向映像中
代码和数据起始的指针这些数值从 ELF 可执行映像的物理头Φ读入,它们描述
的部分也被映射到了进程的虚拟地址空间这也发生在进程的 vm_area_struct 数
据结构建立和页表修改的时候。 mm_struct 数据结构中也包括指针指向传递给
程序的参数和进程的环境变量。
    动态连接的映像反过来,不包含运行所需的所有的代码和数据其中一些放
在共享库并在運行的时候连接到映像中。当运行时动态库连接到映像中的时候动
这些库包括通用的代码,比如语言子例程如果没有动态连接,所有嘚程序都必须
有这些库的独立拷贝需要更多的磁盘空间和虚拟内存。在动态连接的情况下
ELF 映像的表中包括引用的所有库例程的信息。這些信息指示动态连接程序如何定
位库例程以及如何连接到程序的地址空间
    脚本文件是需要解释器才能运行的可执行文件。 Linux 下有大量的解释器
,在脚本文件的第一行包括解释程序的名字所以一个典型的脚本文件可能开头是


    脚本文件加载器试图找出文件所用的解释程序。它试图打开脚本文件第一行指
定的可执行文件如果可以打开,就得到一个指向该文件的 VFS I 节点的指针
然后执行它去解释脚本文件。脚夲文件的名字成为了参数 0 (第一个参数)所
有的其他参数都向上移动一位(原来的第一个参数成为了第二个参数等等)。加载
解释程序囷 Linux 加载其他可执行程序一样 Linux 依次尝试各种二进制格式,
直到可以工作这意味着理论上你可以把几种解释程序和二进制格式堆积起来,讓
 Linux 的二进制格式处理程序更加灵活

我要回帖

更多关于 创作过程的核心部分 的文章

 

随机推荐