极限首页 业界焦点 软件工程师之路 系统工程师之路 网络工程师之路 软件下载 技术社区
 bash编程学习笔记(一)
 RPM 打包技术与典型 SPEC
 Linux Kernel核心中文手册
 Linux Kernel核心中文手册
 精通递归程序设计
 Linux Kernel核心中文手册
 Linux/Unix环境下的make命
 Linux Kernel核心中文手册
 bash编程学习笔记(二)
 Linux操作系统内核编译详解
 bash编程学习笔记(一)
 RPM 打包技术与典型 SPEC
 Linux Kernel核心中文手册
 Linux Kernel核心中文手册
 精通递归程序设计
 Linux Kernel核心中文手册
 Linux/Unix环境下的make命
 Linux Kernel核心中文手册
 bash编程学习笔记(二)
 Linux操作系统内核编译详解

Shell 中文手册

Python 2.3 中文手册

Python 2.4 中文手册

Mysql 4.x 中文手册

PHP 4.x 中文手册

Apache 2.x 中文手册
更多手册

站内搜索:
当前位置:首页>>软件工程师之路>>编程进阶>>正文
Linux Kernel核心中文手册(3、4)(4)
时间:2005-11-08 作者:未知 来源:未知

   


Times and Timer(时间和计时器)

 

核心跟踪进程的CPU时间和其他一些时间。每一个时钟周期,核心更新当前进程的jiffies来表示在系统和用户态下花费的时间总和。

 

除了这些记账的计时器,Linux还支持进程指定的间隔计时器(interval timer)。进程可以使用这些计时器在这些计时器到期的时候发送给自身信号。支持三种间隔计时器:

参见kernel/itimer.c

 

Real 这个计时器使用实时计时,当计时器到期,发送给进程一个SIGALRM信号。

这个计时器只在进程运行的时候计时,到期的时候,发送给进程一个SIGVTALARM信号。

Profile 在进程运行的时候和系统代表进程执行的时候都及时。到期的时候,会发送SIGPROF信号。

 

可以运行一个或者所有的间隔计时器,Linux在进程的task_struct数据结构中记录所有的必要信息。可以使用系统调用建立这些间隔计时 器,启动、停止它们,读取当前的数值。虚拟和profile计时器的处理方式相同:每一次时钟周期,当前进程的计时器递减,如果到期,就发出适当的信号

参见kernel/sched.c do_it_virtual(), do_it_prof()

 

实时间隔计时器稍微不同。Linux使用计时器的机制在第11章描述。每一个进程都有自己的timer_list数据结构,当时使用实时计时器的时 候,使用系统的timer表。当它到期的时候,计时器后半部分处理把它从队列中删除并调用间隔计时器处理程序。它产生SIGALRM信号并重启动间隔计时 器,把它加回到系统计时器队列。

参见:kernel/iterm.c it_real_fn()

 


Executing Programs (执行程序)

 

在Linux中,象Unix一样,程序和命令通常通过命令解释器执行。命令解释程序是和其他进程一样的用户进程,叫做shell(想象一个坚果,把 核心作为中间可食的部分,而shell包围着它,提供一个接口)。Linux中有许多shell,最常用的是sh、bash和tcsh。除了一些内部命令 之外,比如cd和pwd,命令是可执行的二进制文件。对于输入的每一个命令,shell在当前进程的搜索路径指定的目录中(放在PATH环境变量)查找匹 配的名字。如果找到了文件,就加载并运行。Shell用上述的fork机制克隆自身,并在子进程中用找到的执行映像文件的内容替换它正在执行的二进制映像 (shell)。通常shell等待命令结束,或者说子进程退出。你可以通过输入control-Z发送一个SIGSTOP信号给子进程,把子进程停止并 放到后台,让shell重新运行。你可以使用shell命令bg让shell向子进程发送SIGCONT信号,把子进程放到后台并重新运行,它会持续运行 直到它结束或者需要从终端输入或输出。

 

执行文件可以由许多格式甚至可以是一个脚本文件(script file)。脚本文件必须用合适的解释程序识别并运行。例如/bin/sh解释shell script。可执行的目标文件包括了执行代码和数据以及足够的其他信息,时的操作系统可以把它们加载到内存中并执行。Linux中最常用的目标文件类型 是ELF,而理论上,Linux灵活到足以处理几乎所有的目标文件格式。

好像文件系统一样,Linux可以支持的二进制格式也是在核心连接的时候直接建立在核心的或者是可以作为模块加载的。核心保存了支持的二进制格式 (见图4.3)的列表,当试图执行一个文件的时候,每一个二进制格式都被尝试,直到可以工作。通常,Linux支持的二进制文件是a.out和ELF。可 执行文件不需要完全读入内存,而使用叫做demand loading的技术。当进程使用执行映像的一部分的时候它才被调入内存,未被使用的映像可以从内存中废弃。 参见fs/exec.c do_execve()

 


ELF

 

ELF(Executable and Linkable Format 可执行可连接格式)目标文件,由Unix系统实验室设计,现在成为Linux最常用的格式。虽然和其他目标文件格式比如ECOFF和a.out相比,有性 能上的轻微开支,ELF感觉更灵活。ELF可执行文件包括可执行代码(有时叫做text)和数据(data)。执行映像中的表描述了程序应该如何放到进程 的虚拟内存中。静态连接的映像是用连接程序(ld)或者连接编辑器创建的,单一的映像中包括了运行该映像所需要的所有的代码和数据。这个映像也描述了该映 像在内存中的布局和要执行的第一部分代码在映像中的地址。

 

图4.4象是了静态连接的ELF可执行映像的布局。这是个简单的C程序,打印“hello world”然后退出。头文件描述了它是一个ELF映像,有两个物理头(e_phnum这个计时器只在进程FACE="宋体" LANG="ZH-CN" SIZE=3>),从映像文件的开头第52字节开始(e_phoff)。第一个物理头描述映像中的执行代码,在虚拟地址0x8048000,有 65532字节。因为它是静态连接的,所以包括输出“hello world”的调用printf()的所有的库代码。映像的入口,即程序的第一条指令,不是位于映像的起始位置,而在虚拟地址0x8048090 (e_entry)。代码紧接着在第二物理头后面开始。这个物理头描述了程序的数据,将会加载到虚拟内存地址0x8059BB8。这块数据可以读写。你会 注意到文件中数据的大小是2200字节(p_filesz)而在内存中的大小是4248字节。因为前2200字节包括预先初始化的数据,而接着的2048 字节包括会被执行代码初始化的数据。

参见include/linux/elf.h

 

当Linux把ELF可执行映像加载到进程的虚拟地址空间的时候,它不是实际的加载映像。它设置虚拟内存数据结构,即进程的 vm_area_struct和它的页表。当程序执行了page fault的时候,程序的代码和数据会被放到物理内存中。没有用到的程序部分将不会被放到内存中。一旦ELF 二进制格式加载程序满足条件,映像是一个有效的ELF可执行映像,它把进程的当前可执行映像从它的虚拟内存中清除。因为这个进程是个克隆的映像(所有的进 程都是),旧的映像是父进程执行的程序的映像(例如命令解释程序shell bash)。清除旧的可执行映像会废弃旧的虚拟内存的数据结构,重置进程的页表。它也会清除设置的其他信号处理程序,关闭打开的文件。在清除过程的最后, 进程准备运行新的可执行映像。不管可执行映像的格式如何,进程的mm_struct中都要设置相同的信息。包括指向映像中代码和数据起始的指针。这些数值 从ELF可执行映像的物理头中读入,它们描述的部分也被映射到了进程的虚拟地址空间。这也发生在进程的vm_area_struct数据结构建立和页表修 改的时候。mm_struct数据结构中也包括指针,指向传递给程序的参数和进程的环境变量。

 

ELF Shared Libraries(ELF共享库)

 

动态连接的映像,反过来,不包含运行所需的所有的代码和数据。其中一些放在共享库并在运行的时候连接到映像中。当运行时动态库连接到映像中的时候, 动态连接程序(dynamic linker)也要使用ELF共享库的表。Linux使用几个动态连接程序,ld.so.1,libc.so.1和ld-linux.so.1,都在 /lib目录下。这些库包括通用的代码,比如语言子例程。如果没有动态连接,所有的程序都必须有这些库的独立拷贝,需要更多的磁盘空间和虚拟内存。在动态 连接的情况下,ELF映像的表中包括引用的所有库例程的信息。这些信息指示动态连接程序如何定位库例程以及如何连接到程序的地址空间。

 


Scripts Files

 

脚本文件是需要解释器才能运行的可执行文件。Linux下有大量的解释器,例如wish、perl和命令解释程序比如tcsh。Linux使用标准的Unix约定,在脚本文件的第一行包括解释程序的名字。所以一个典型的脚本文件可能开头是:

#!/usr/bin/wish

 

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

参见fs/binfmt_script.c do_load_script()


  共4页: 上一页 [1] [2] [3] 4   
推荐】【 】【关闭


关于极限 | 站内地图 | 意见反馈 | 广告服务 | 数据服务 | 联系我们
本站所刊登的文章,技术资料,软件均整理于网络资源或本站原创,转载请务必联系原作者或本站。
Copyright ? 2001-2004 UPLinux.com All Rights Reserved.
本站唯一联系信箱:
京ICP备05010519