摘  要

本文完整描述了一个简单的应用程序在Linux系统下运行的整个生命周期。从源程序作为起点,经历编译、链接,一直到加载、运行,再到终止、回收。这个过程涉及到底层硬件及操作系统的多个方面,完整体现了在当代计算机下一个程序执行的全过程。整个探索的过程充分体现了整个课程丰富的知识框架。

关键词:生命周期;内存管理;编译;                           

目  录

第1章 概述............................................................................................................. - 4 -

1.1 Hello简介...................................................................................................... - 4 -

1.2 环境与工具..................................................................................................... - 4 -

1.3 中间结果......................................................................................................... - 4 -

1.4 本章小结......................................................................................................... - 4 -

第2章 预处理......................................................................................................... - 5 -

2.1 预处理的概念与作用..................................................................................... - 5 -

2.2在Ubuntu下预处理的命令.......................................................................... - 5 -

2.3 Hello的预处理结果解析.............................................................................. - 5 -

2.4 本章小结......................................................................................................... - 5 -

第3章 编译............................................................................................................. - 6 -

3.1 编译的概念与作用......................................................................................... - 6 -

3.2 在Ubuntu下编译的命令............................................................................. - 6 -

3.3 Hello的编译结果解析.................................................................................. - 6 -

3.4 本章小结......................................................................................................... - 6 -

第4章 汇编............................................................................................................. - 7 -

4.1 汇编的概念与作用......................................................................................... - 7 -

4.2 在Ubuntu下汇编的命令............................................................................. - 7 -

4.3 可重定位目标elf格式................................................................................. - 7 -

4.4 Hello.o的结果解析...................................................................................... - 7 -

4.5 本章小结......................................................................................................... - 7 -

第5章 链接............................................................................................................. - 8 -

5.1 链接的概念与作用......................................................................................... - 8 -

5.2 在Ubuntu下链接的命令............................................................................. - 8 -

5.3 可执行目标文件hello的格式.................................................................... - 8 -

5.4 hello的虚拟地址空间.................................................................................. - 8 -

5.5 链接的重定位过程分析................................................................................. - 8 -

5.6 hello的执行流程.......................................................................................... - 8 -

5.7 Hello的动态链接分析.................................................................................. - 8 -

5.8 本章小结......................................................................................................... - 9 -

第6章 hello进程管理................................................................................... - 10 -

6.1 进程的概念与作用....................................................................................... - 10 -

6.2 简述壳Shell-bash的作用与处理流程..................................................... - 10 -

6.3 Hello的fork进程创建过程..................................................................... - 10 -

6.4 Hello的execve过程................................................................................. - 10 -

6.5 Hello的进程执行........................................................................................ - 10 -

6.6 hello的异常与信号处理............................................................................ - 10 -

6.7本章小结....................................................................................................... - 10 -

第7章 hello的存储管理................................................................................ - 11 -

7.1 hello的存储器地址空间............................................................................ - 11 -

7.2 Intel逻辑地址到线性地址的变换-段式管理............................................ - 11 -

7.3 Hello的线性地址到物理地址的变换-页式管理....................................... - 11 -

7.4 TLB与四级页表支持下的VA到PA的变换............................................. - 11 -

7.5 三级Cache支持下的物理内存访问.......................................................... - 11 -

7.6 hello进程fork时的内存映射.................................................................. - 11 -

7.7 hello进程execve时的内存映射.............................................................. - 11 -

7.8 缺页故障与缺页中断处理........................................................................... - 11 -

7.9动态存储分配管理....................................................................................... - 11 -

7.10本章小结..................................................................................................... - 12 -

第8章 hello的IO管理................................................................................. - 13 -

8.1 Linux的IO设备管理方法.......................................................................... - 13 -

8.2 简述Unix IO接口及其函数....................................................................... - 13 -

8.3 printf的实现分析........................................................................................ - 13 -

8.4 getchar的实现分析.................................................................................... - 13 -

8.5本章小结....................................................................................................... - 13 -

结论......................................................................................................................... - 14 -

附件......................................................................................................................... - 15 -

参考文献................................................................................................................. - 16 -

第1章 概述

1.1 Hello简介

P2P:通过在文本编辑器里写下Hello.c的源代码,经过编译器进行预处理、编译、汇编、链接的过程,将源代码翻译成汇编语言,再翻译成机器语言,能够被硬件识别以及执行相应的指令。接着在面向用户的Shell里,通过创建子进程,调用生成的Hello可执行程序,同时为其分配虚拟内存以及运行时所占用的时间片,使得程序得以在CPU等硬件上运行。

020:在程序开始运行前不占用任何运行资源;当运行时操作系统为其分配内存空间以及执行时间以及相应的计算资源;运行结束后,操作系统杀死该进程,回收所有的资源,归于平静。

1.2 环境与工具

硬件环境:12th Gen Intel(R) Core(TM) i7-12700H 2.30 GHz;16.0 GB。

软件环境:Windows 11 64位;VMWare Workstation 17 Player;Ubuntu 23.10。

开发工具:gcc;edb;vim;objdump;readelf;as;ld。

1.3 中间结果

Hello.i:Hello.c文件经过预处理之后生成的源代码;

Hello.s:Hello.i文件经过编译后生成的汇编代码;

Hello.o:Hello.s文件经过汇编后生成的目标文件;

Hello:Hello.s文件在与其他文件进行链接后形成的可执行程序。

1.4 本章小结

       本章节描述了整个大作业的概况。

第2章 预处理

2.1 预处理的概念与作用

预处理指将源代码通过预处理程序翻译成更容易被编译器进行处理的单个文件。比如将调用的头文件(header)全部展开,将定义的宏(define)进行展开,在实际编译时编译器只需要对单个文件进行编译。

经过预处理后的程序可以被编译器进行编译生成汇编程序。

2.2在Ubuntu下预处理的命令

通过在源代码所在目录下执行命令gcc -E hello.c -o hello.i,将hello.c预处理。

2.3 Hello的预处理结果解析

预处理结果前面部分是Hello.c里面涉及到的所有的宏(包括对头文件的引用,以及嵌套引用)进行展开之后的结果。所有用井号标注的行为注释,表示在展开前这部分属于哪个文件的哪个部分。

同时预处理还删除了整个过程中出现的所有注释。

2.4 本章小结

本章节简要介绍了Hello.c程序进行预处理的结果以及作用。

预处理只是简单的文本拼接,经过预处理之后生成的程序仍然是文本文件。但是预处理之后的文件才可以被编译器做进一步处理。

第3章 编译

3.1 编译的概念与作用

编译指经过预处理后的高级语言源代码,通过所处操作系统下编译器的编译操作,将高级语言表述的各种功能逐条描述成汇编语言的过程。

汇编语言贴近于计算机实际使用的CPU指令,可以按照相应的指令集翻译成对应的机器语言,是编译成可执行程序之前的最后一步操作;同时汇编语言保留了一定的可读性,开发者尚可根据汇编指令理解程序的运行细节。

3.2 在Ubuntu下编译的命令

3.3 Hello的编译结果解析

3.3.1 数据存储

       在Hello.c源代码中出现的量有如下几种:

常量,如“用法: Hello 学号 姓名 秒数!\n”、“Hello %s %s\n”等。这些常量被存放在text段,是只读形式的字符串。变量,如在main函数内定义的i。这些量会在运行时存储在堆栈当中,因此在调用之前栈指针会发生偏移,用于存放这些变量。参数,如在main函数参数列表里的argc和argv。这些参数会在调用main函数之前压入栈中,不由main函数分配空间,而需要外部程序在调用main函数之前提前放到堆栈当中。

3.3.2 运算符

赋值语句通过mov指令实现;比较语句通过cmp指令实现;对地址的解引用,通过对指针所指向的地址进行偏移,并读取其中的数值实现。

3.3.3 判断语句

判断语句通过cmpl和je语句实现。具体来说,cmpl语句会将argc的值与4进行比较,存放进寄存器里;je语句则会根据寄存器当中的结果进行跳转。如果argc和4相等,则会直接跳转到L2;而如果不等,则继续执行下列语句(输出提示并终止程序)。

3.3.4 循环语句

For循环三个内容分别对应着L2、L3、L4最后一部分。先执行L2内的语句进行循环前的初始化,接着跳转进L3判断是否需要执行循环。如果满足条件,就会跳进L4执行循环体内的内容,并在最后执行i++,接着进入L3,如此往复。

3.3.5 函数调用

函数调用主要通过call、leave、ret指令实现。在进行函数调用之前,程序会向堆栈中推入被调用函数所需要使用的参数(对于64位操作系统,若传入的参数数量较少,则会直接使用寄存器用于传参)。接着执行call指令,此时会推入当前代码的行数,并跳转进入被调用函数的片段,而leave指令用于收尾操作还原栈指针,ret指令则是让程序跳转回调用它的代码语句。

3.4 本章小结

本章节介绍了从预处理后的源代码经过编译生成汇编语言的过程。

第4章 汇编

4.1 汇编的概念与作用

汇编指经过编译生成的汇编源码,经过汇编程序根据相应平台的指令集将汇编代码逐条翻译成可被CPU直接识别的机器码的过程。

经过汇编后的代码已经完全变成了只可被机器识别的机器代码,只暴露一些函数接口及全局变量等,不再可读。通过链接上一些必要的文件,程序即可被执行。

4.2 在Ubuntu下汇编的命令

4.3 可重定位目标elf格式

 

4.4 Hello.o的结果解析

机器语言由二进制01串构成,每条指令由长短不一的01数字进行编码,越常用的指令的编码通常越短。汇编语言由文本写成,基本上逐条描述机器语言的每一条指令,但是汇编语言当中可能会有一些别的助记符号。

在分支转移函数的调用当中,汇编语言会给特定的语段加上记号,比如jmp .L3 表示跳转到 L3 记号所在处。但是当汇编语言翻译成机器语言后,操作数就变成了L3记号所对应的语句的地址。

4.5 本章小结

本章节简述了编译器将汇编语言翻译成机器语言的过程,简要阐述了机器语言与汇编语言的区别。

第5章 链接

5.1 链接的概念与作用

链接指将一个或多个由编译器或汇编器生成的目标文件外加库,链接为一个可执行文件的过程。

编写程序时可能会调用到一些别的函数,例如系统函数。这些函数所对应的机器码并不在源代码当中,编译完成的目标文件想要执行,就需要与这些外部的目标文件进行链接,进而程序才能调用那些原本不属于自己的函数。通过链接可以大大简化用户编写程序的过程。

5.2 在Ubuntu下链接的命令

5.3 可执行目标文件hello的格式

5.4 hello的虚拟地址空间

    使用edb加载hello,查看本进程的虚拟地址空间各段信息,并与5.3对照分析说明。  

5.5 链接的重定位过程分析

两者主要有以下不同:

新增加了诸如puts、printf、sleep等段。这是因为经过动态链接之后这些函数的代码加入到了可执行文件当中;新增加了诸如.init和.plt等节,这些是程序执行所不可缺少的节。一些逻辑地址在经过链接之后变成了虚拟地址。

重定位的主要方式是,(1)将相同的节合并到一起;(2)在合并之后确定一些先前没有确定下来的地址。

5.6 hello的执行流程

在加载 hello之前,首先调用了/lib/x86_64-linux-gnu/libthread_db.so.1动态链接库。在此之后进入_start函数开始执行hello的主要代码。调用main之前,依次执行了:

_init();_frame_dummy();_register_tm_clones();main();

在调用main函数之后,反复调用执行printf函数以及sleep函数。最后依次调用了:

__do_global_dtors_aux();deregister_tm_clones ();_fini ();

最终退出程序。

5.7 Hello的动态链接分析

使用readelf查看生成的hello文件,可以发现其中的.got段的起始位置为0x403fd8,大小为0x10。

在程序进行dl_init之前,可以发现got表当中的元素都是0x00。而当进行dl_init之后,got表当中的元素被填上了偏移量,表示程序想要调用这些外部函数需要从哪个地址去寻找。

5.8 本章小结

本章节主要介绍了在hello程序的链接过程,以及在运行时发生的动态链接的过程。

第6章 hello进程管理

6.1 进程的概念与作用

进程是正在运行的程序的实例,一个进程可以向操作系统申请内存及运算资源。执行一个程序的过程,就是操作系统创建并执行一个进程的过程。

进程被用来描述每个程序的运行情况,反映了一个计算机里正在运行的程序。操作系统可以通过管理这些进程从而实现对不同程序的管理。进程之间也可以发生不同的交互,以实现更复杂的过程。

6.2 简述壳Shell-bash的作用与处理流程

Shell-bash是面向用户的命令窗口。用户通过在shell里输入指令,可以操作计算机执行不同的指令,以及管理不同的程序进程。用户可以打开Shell,键入指令来开始执行程序,当程序执行完毕后执行的结果会被反馈到Shell上。当关闭Shell之后操作系统会回收所有的资源。

6.3 Hello的fork进程创建过程

Fork进程时,操作系统将会检测用户是否能够创建一个新的进程,若能创建,则会设置该进程的各种信息,并为其分配优先级便于内核进行调度。同时,操作系统会复制及共享当前Shell进程占用的资源,用于执行该子进程。

6.4 Hello的execve过程

当执行execve时,Hello程序编译生成的elf文件将会被装载进当前进程里,覆盖掉原先属于Shell的内存。此时该进程完全交给Hello程序。

6.5 Hello的进程执行

CPU会给每个进程分配对应的时间片,由于CPU的运转效率较高,看上去不同的进程是在同时进行的。下文将Shell进程和Hello进程分别称作A进程和B进程。CPU执行时,会轮番执行这两个进程内的代码。假定当前处于用户态, 并处于A进程被CPU运行的状态。一段时间后,用户态被切换为核心态,系统内核将A进程的寄存器值保存到堆栈中,将B进程原先的寄存器值还原,接着切换回用户态执行进程B。当进程B执行了一段时间后,当前状态再次切换为用户态,系统内核保存B进程的寄存器并装载A进程的寄存器。如此循环往复进行进程的调度,使得用户感觉两个进程在同时进行。

6.6 hello的异常与信号处理

 hello执行过程中会出现哪几类异常,会产生哪些信号,又怎么处理的。

 程序运行过程中可以按键盘,如不停乱按,包括回车,Ctrl-Z,Ctrl-C等,Ctrl-z后可以运行ps  jobs  pstree  fg  kill 等命令,请分别给出各命令及运行结截屏,说明异常与信号的处理。

正常执行hello程序:

进程收到的信号:无;

进程收到的异常:

时钟中断:不处理;系统调用:调用write函数打印字符;缺页异常:交由缺页异常处理程序。

按下Ctrl+Z操作:

进程收到的信号:SIGSTOP;

进程收到的异常:

处理器中断:不处理;

执行ps命令:

执行jobs指令:

执行pstree指令:

执行fg指令:

执行kill指令:

6.7本章小结

       本章节简要介绍了hello程序在程序运行过程中对信号以及异常的处理机制,简述了诸如时钟中断、系统调用、缺页异常等异常发生的情况下hello程序的处理机制,也简要说明了hello程序在运行过程中接收到的信号。

第7章 hello的存储管理

7.1 hello的存储器地址空间

虚拟地址:是由程序产生的由段选择符和段内偏移地址组成的地址。这2部分组成的地址并不能直接访问物理内存,而是要通过分段地址的变化处理后才会对应到相应的物理内存地址。例如hello.c当中,在主函数里定义的变量i,它的虚拟地址可以视作main对应的这一段的偏移量加上i在这一段内偏移地址组成。

逻辑地址:指由程序产生的段内偏移地址。逻辑地址与虚拟地址二者之间没有明确的界限。hello.c当中变量i的虚拟地址和逻辑地址可视作相同。

线性地址:指虚拟地址到物理地址变换的中间层,是处理器可寻址的内存空间(称为线性地址空间)中的地址。程序代码会产生逻辑地址,或者说段中的偏移地址,加上相应段基址就成了一个线性地址。经过段式管理以后,i的地址将会变成线性地址。

物理地址:指内存中物理单元的集合,他是地址转换的最终地址,进程在运行时执行指令和访问数据最后都要通过物理地址来存取主存。

7.2 Intel逻辑地址到线性地址的变换-段式管理

段式管理的基本思想是把程序按内容或过程函数关系分成段,每段有自己的名字。一个用户作业或者进程所包含的段对应一个二维线性虚拟空间,也就是一个二维虚拟存储器。段式管理程序以段为单位分配内存,然后通过地址映射机构把段式虚拟地址转换为实际内存物理地址。

Hello.c当中每个函数对应着线性地址上的一个段,每个段所占有的内存也是一个段。每个函数内的变量地址会被映射到线性地址上面。

7.3 Hello的线性地址到物理地址的变换-页式管理

页式管理的基本原理是将各进程的虚拟空间划分为若干个长度相等的页。把内存空间按页的大小划分为片或者页面,然后把页式虚拟地址与内存地址建立一一对应的页表,并用相应的硬件地址转换机构来解决离散地址变换问题。页式管理采用请求调页和预调页技术来实现内外存存储器的统一管理。

Hello.c当中所有变量所占用的地址可以视作一整条线性地址。线性地址的总长度可能超过内存硬件所能接受的地址的长度。这条地址会被操作系统分成若干页,每一页上的地址又会在被使用时被映射到物理地址。

7.4 TLB与四级页表支持下的VA到PA的变换

TLB:页表常驻内存,地址翻译时MMU需要去内存中访问,为减少这样的开销,MMU中包含了一个关于PTE的小缓存,称为翻译后备缓冲器(TLB)。

多级页表:将页表分为多个层级,以减少内存要求。

由TLBI,访问TLB中的某一组,遍历该组中的所有行,若找到一行的tag等于TLBT,且有效位valid为1,则缓存命中,该行存储的即为PPN;否则缓存不命中,需要到页表中找到被请求的块替换原TLB表项中的块。

多级页表的访问:缓存不命中后,VPN被解释成从低位到高位的等长的4段,从高地址开始,第一段VPN作为第一级页表的索引,用以确定第二级页表的基址;第二段VPN作为第二级页表的索引,用以确定第三级页表的基址;第三段VPN作为第三级页表的索引,用以确定第四级页表的基址;第四段VPN作为第四级页表的索引,若该位置的有效位为1,则第四级页表中的该表项存储的是所需要的PPN的值。

7.5 三级Cache支持下的物理内存访问

CPU将物理地址解释为三部分:CT(缓存标记),CI(组索引),CO(块偏移)。

首先根据组索引CI,遍历缓存中对应组的所有行,若找到一行的tag等于CT,且标志位valid为1,则缓存命中(hit),根据CO(块偏移)读取块中对应的数据;否则缓存不命中。

若缓存不命中,则向下一级缓存中查找数据(一级Cache、二级Cache、三级Cache、主存、磁盘)。找到数据之后,开始进行行替换。若该组中有空行,那就将数据缓存至这个空行,并设置tag和valid位;若该组中没有空行,根据一些策略来决定驱逐哪一行,如最不常使用(LFU)策略和最近最少使用(LRU)策略。LFU策略会替换过去某个时间段内访问次数最少的那一行,LRU策略会替换最后一次访问时间最久远的那一行。

7.6 hello进程fork时的内存映射

当前进程调用fork函数时,内核会为新进程创建各种数据结构,并分配给它一个唯一的PID。为了给这个新流程创建虚拟内存,它创建了当前流程的mm_struct,区域结构和页表的原样副本。它将两个进程中的每个页面标记为只读,并将两个进程中的每个区域结构标记为私有的写时复制。

当fork在新进程中返回时,新进程现在的虚拟内存刚好和调用fork时存在的虚拟内存完全相同。当这两个进程的任一个后来进行写操作时,写时复制机制就会创建新页面,因此,也就为每个进程保持了私有地址空间的抽象概念。

7.7 hello进程execve时的内存映射

execve函数在当前进程的上下文中加载并执行可执行目标文件hello 中的程序。加载并运行hello 需要执行以下步骤:

删除已存在的用户区域。删除当前进程虚拟地址的用户部分中的已存在的区域结构。映射私有区域。为新程序的代码、数据、bss 和栈区域创建新的区域结构,所有这些新的区域都是私有的、写时复制的。代码和数据区域被映射为hello 文件中的.text 和.data 区,bss 区域是请求二进制零的,映射到匿名文件,其大小包含在hello 中,栈和堆地址也是请求二进制零的,初始长度为零。映射共享区域。hello 程序与共享对象libc.so 链接,libc.so 是动态链接到这个程序中,然后再映射到用户虚拟地址空间中的共享区域内。设置程序计数器(PC),execve 做的最后一件事情就是设置当前进程上下文的程序计数器,使之指向代码区域的入口点。

7.8 缺页故障与缺页中断处理

缺页故障是一种常见的故障,当指令引用一个虚拟地址,在MMU 中查找页表时发现与该地址相对应的物理地址不在内存中,因此必须从磁盘中取出的时候就会发生故障。

缺页中断处理:缺页处理程序是系统内核中的代码,选择一个牺牲页面,如果这个牺牲页面被修改过,就将其写回,然后换入新的页面并更新页表。缺页处理程序返回时,CPU重新启动引起缺页的指令,这条指令再次发送 VA 到 MMU,这次 MMU 就能正常翻译 VA 了。

7.9动态存储分配管理

动态内存分配器维护着一个进程的虚拟内存区域,称为堆。分配器将堆视为一组不同大小的块的集合来维护。每个块就是一个连续的虚拟内存片,要么是已分配的,要么是空闲的。已分配的块显式地保留为供应用程序使用。空闲块可用来分配。空闲块保持空闲,直到它显式地被应用所分配。一个已分配的块保持已分配状态,直到它被释放,这种释放要么是应用程序显式执行的,要么是内存分配器自身隐式执行的。

7.10本章小结

本章主要介绍了hello的存储器地址空间、intel的段式管理、hello的页式管理,介绍了VA 到PA 的变换、物理内存访问,还介绍了hello 进程 fork 时的内存映射、execve 时的内存映射、缺页故障与缺页中断处理、动态存储分配管理。第8章 hello的IO管理

8.1 Linux的IO设备管理方法

设备的模型化:所有的IO设备都被模型化为文件设备管理。

设备管理:所有的输入和输出都被当做对相应文件的读和写来执行,这种将设备映射为文件的方式,允许Linux内核引出一个简单,低级的应用接口,称为Unix I/O。

8.2 简述Unix IO接口及其函数

8.2.1接口

打开文件:一个应用程序通过要求内核打开相应的文件,来说明它想要访问一个I/O设备,内核返回一个小的非负整数,叫做描述符,它在后续对此文件的所有操作中标识这个文件,内核记录有关这个打开文件的所有信息。

改变当前文件位置:对于每个打开的文件,内核保持着一个文件位置p,初始为0,这个文件位置是从文件开头起始的字节偏移量,应用程序能够通过执行seek,显式地将改变当前文件位置p。

读写文件:一个读操作就是从文件复制一定个数的字节到内存,从当前文件位置p开始,然后将p增加到p+n。假设当前打开的文件的大小为m字节,当p>=m时执行读操作就会触发EOF。而写操作则是将n个字节写入到文件当中去,同时将p修改为p+n。

关闭文件:当应用完成了访问,它就通知内核关闭这个文件,并释放文件打开时创建的数据结构,并将这个描述符恢复到可用的描述符池中去。

8.2.2 函数

int open(char* filename, int flags, mode_t mode):打开文件。进程通过调用open函数来打开一个存在的文件或是创建一个新文件。open函数将filename转换为一个文件描述符,并且返回描述符数字,返回的描述符总是在进程中当前没有打开的最小描述符,flags参数指明了进程打算如何访问这个文件,mode参数指定了新文件的访问权限位。

int close(fd):关闭文件。fd是需要关闭文件的描述符。

size_t read(int fd, void *buf, size_t n):从描述符为fd的当前位置最多赋值n个字节到内存buf的位置,返回值为实际传送的字节数量。

size_t wirte(int fd, const void *buf, size_t n):从内存位置buf复制至多n个字节到描述符为fd的当前文件位置。

8.3 printf的实现分析

从vsprintf生成显示信息,到write系统函数,到陷阱-系统调用 int 0x80或syscall等。

字符显示驱动子程序:从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)。

显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量)。

8.4 getchar的实现分析

异步异常-键盘中断的处理:键盘接口得到一个代表该按键的键盘扫描码,同时同时产生中断请求,请求抢占当前进程运行键盘中断子程序,中断子程序先从键盘接口取得该按键的扫描码,然后将该按键扫描码转换成ASCII码,保存到系统的键盘缓冲区之中。

8.5本章小结

本章主要介绍了 Linux 的 IO 设备管理方法、Unix IO 接口及其函数,了解了 printf 函数和 getchar 函数的实现。

结论

Hello程序依次经过了预处理、编译、汇编、链接形成了可执行程序。

接着,用户打开Shell程序,创建新的进程,并且执行Hello程序。此时Shell进程将会利用fork函数创建子进程,同时使用execve函数将该进程的内存等交由hello程序运行。

在执行过程中,Hello 会向操作系统申请内存。Hello当中每个变量的地址会依次经过段式管理和页式管理,从逻辑地址转变为线性地址,再转变为物理地址。在此过程中会涉及到多级页表以及多级Cache对内存进行管理。

再执行过程中,Hello还会涉及到中断以及信号。例如,在调用sleep函数时会产生系统中断,在页缺失的时候会发生缺页中断。这些中断使得Hello程序可以实现各种功能。同时Hello还会受到Shell进程发给它的信号。

在Hello程序执行时,还会与用户发生交互。例如,用户向程序当中键入文字、Hello向屏幕上打印文字,这些都涉及到Linux系统底层的IO交互。通过不同函数的协同作用Hello得以完成IO交互。

附件

Hello.i:Hello.c文件经过预处理之后生成的源代码;

Hello.s:Hello.i文件经过编译后生成的汇编代码;

Hello.o:Hello.s文件经过汇编后生成的目标文件;

Hello:Hello.s文件在与其他文件进行链接后形成的可执行程序。

参考文献

[1]  林来兴. 空间控制技术[M]. 北京:中国宇航出版社,1992:25-42.

[2]  辛希孟. 信息技术与信息服务国际研讨会论文集:A集[C]. 北京:中国科学出版社,1999.

[3]  赵耀东. 新时代的工业工程师[M/OL]. 台北:天下文化出版社,1998 [1998-09-26]. http://www.ie.nthu.edu.tw/info/ie.newie.htm(Big5).

[4]  谌颖. 空间交会控制理论与方法研究[D]. 哈尔滨:哈尔滨工业大学,1992:8-13.

[5]  KANAMORI H. Shaking Without Quaking[J]. Science,1998,279(5359):2063-2064.

[6]  CHRISTINE M. Plant Physiology: Plant Biology in the Genome Era[J/OL]. Science,1998,281:331-332[1998-09-23]. http://www.sciencemag.org/cgi/ collection/anatmorp.

文章来源

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: