HIT-ICS大作业-程序人生

种地  论坛元老 | 2025-2-14 06:28:26 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1047|帖子 1047|积分 3141




 

计算机系统


大作业



题     目  程序人生-Hello’s P2P 
专       业  数据科学与大数据技能    
学     号         2021112608      
班     级        2103501          
学       生         贺荣奇          
指 导 教 师          史先俊          






计算机科学与技能学院

2023年4月

摘  要

程序的一生在程序员的眼里是透明的,这篇文章我们将从hello在linux下的运行的一生来分析,先容了预处理、编译、汇编、毗连、接纳的整个过程及原理,同时也涉及到存储管理、进程管理、i/o控制。

关键词:预处理;编译;汇编;链接;进程管理;存储管理;linux;I/O                                     

(摘要0分,缺失-1分,根据内容精彩称都酌情加分0-1分









目  录


第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简介

Hello程序最初以hello.c的文件存放在磁盘中,之后通过我们编译器驱动器(gcc)的编译下,首先辈行预处理,天生hello.i文件,主要是睁开头文件并将定义的宏赋值。然后颠末编译步调,天生汇编代码,也就是hello.s文件。之后通过汇编器(AS)对文件进行进一步转化,天生hello.o文件(可重定位目标文件)之后再通过链接器(LD)链接,天生可执行文件。 在shell中进入对应目次并输入./hello运行hello程序,shell会为这个程序fork子进程,此时由Program转变成了Process。

(020)文件的运行,首先在终端(Terminal)下,输入命令gcc hello.c,完成对上述文件的天生(中心文件不保留),得到hello.out文件,而后输入命令./hello.out,这时shell会创建一个子进程(fork()),将程序hello.out加载之内存中该子进程的上下文中(execve()),通过流水线化的CPU来处理该程序。在程序执行竣事之后,盖子进程会变为一个僵死进程,发送一个信号(SIGCHLD)给shell,shell会往返收该子进程(将其从内存中删除),操纵系统内核删除其相关信息,释放它所占用的内存空间。
1.2 环境与工具

硬件环境:X64 CPU intel core i7
软件环境:VMware ,Ubuntu22.04
开发工具:vim,gedit,codeblocks,edb
1.3 中心效果

文件名
作用
Hello.c
源程序
Hello.i
预处理后的文件
Hello.s
汇编文件
Hello.o
可重定位目标执行文件
Hello
可执行文件
Hello.elf
Hello.o的elf文件
Hello_asm.txt
Hello.o的反汇编
Hello1_asm.txt
Hello的反汇编
Hello1.elf
Hello的elf
1.4 本章小结

在这一章中,我们开始了对HELLO的一生的剖析,翻译了p2p和020在程序中的意思。先容了中心效果和实行环境。
(第1章0.5分)




第2章 预处理

2.1 预处理的概念与作用

与处理的概念:程序设计领域中,预处理一样平常是指在程序源代码被翻译为目标代码的过程中,天生二进制代码之前的过程。典范地,由预处理器(preprocessor) 对程序源代码文本进行处理,得到的效果再由编译器核心进一步编译。

预处理的作用:源文件颠末预处理可以得到便于编译器工作的.i文件


2.2在Ubuntu下预处理的命令

利用gcc -E hello.c -o hello.i

 
图2.1预处理命令


2.3 Hello的预处理效果解析



 
图2.2hello.i文件

这里可以看到预处理后的hello.i文件有3091行。
这是由于头文件中的代码以函数的形式编入了此文件中。搜索后发现果然如此。分析了三个头文件stdio.h、stdlib.h、unistd.h均已经被预处理。

 
图2.3hello.i中头文件部分

2.4 本章小结

      本章先容了预处理的概念以及作用(包括头文件的睁开、宏替换、去掉注释、条件编译等),在ubuntu上输入命令进行测试,然后分析了hello.c到hello.i的过程和代码变革。

学习到了预处理的利用方法及长处:合理的利用预处理功能编写的程序便于阅读、修改、移植和调试,也有利于模块化程序设计。
(第2章0.5分)


第3章 编译

3.1 编译的概念与作用

3.1.1概念:
c语言是对汇编语言的抽象,汇编语言是对硬件的抽象,编译过程是整个程序构建的核心部分,会将源代码由文本形式转换成机器语言,编译过程就是把预处理完的文件进行一系列词法分析、语法分析、语义分析以及优化后天生相应的.s汇编代码文件,文件内是汇编语言。

3.1.2作用:
把源程序(高级语言)翻译成汇编语言。其包括以下几个步调:
1、词法分析:词法分析是编译器的第一个步调,它也被称为扫描。词法分析器通过读取源程序的字符流对其进行扫描,并且把它们构成故意义的词素(lexeme)序列,并产生词法单元(token) 作为输出,传递给语法分析。
词素是 token 的实例,词法分析器的主要任务就是从源程序中读取字符并产生 token。token 的布局为<token-name, attribute-value>,token-name代表分析的抽象符号,attribute-value指向符号表中该条目标位置。
符号表能够记录源程序中利用变量的名称,并收集和每个名称相关的属性信息,比方变量的存储分配、范例、作用域,对于过程方法还有参数范例、传递方法、返回范例。符号表为每个变量创建一个记录条目,编译器可以敏捷查找到记录并对其进行存取。
2.语法分析:语法分析又称为 解析。语法分析器利用词法单元的第一个分量来创建树形的中心表现–语法树。树中的每个非叶节点都表现一个运算,其左右子节点表现运算的分量。编译器的后续步调都会利用这个语法布局来帮助分析源程序,并声称目标程序。
3、中心代码:源程序的一种内部表现,或称中心语言。中心代码的作用是可使编译程序的布局在逻辑上更为简单明确,特殊是可使目标代码的优化比较轻易实现中心代码。
4、目标代码天生与优化:代码天生器将中心代码转成机器代码,这个过程是依靠于目标机器的,由于差别的机器有着差别的字长、寄存器、数据范例等。最后目标代码优化器对目标代码进行优化,比如选择符合的寻址方式、利用位移来代替乘除法、删除出多余的指令等。
注意:这儿的编译是指从 .i 到 .s 即预处理后的文件到天生汇编语言程序
       

3.2 在Ubuntu下编译的命令


 
图3.1编译命令


 
图3.2文件天生

3.3 Hello的编译效果解析

3.3.1数据
      (1)常量
      观察初始C语言代码

 
图3.3源程序代码

发现初始的常量有argv这个4,以及i这个5.找到在.s文件中对应的


 
图3.4常量一

这里直接转换为立即数4,与变量作比较。另一个5在

 
图3.5常量2

这里是立即数4与变量作比较假如小于等于进入循环。
字符串:原文中有两个字符串

 
图3.6常量3

被存成了只读字符串。
(2).变量
全局变量、静态变量:本代码中没有。
局部变量:

 
图3.7变量1源

利用是在for循环中利用。以是我们只要找循环判断条件的出口处就能找到这个变量,

 
图3.8变量1

得知是存在了栈中,通过栈顶地点加上偏移量来访问。
hello.c中的其他局部变量还包括argc和argv,同样地,它们都存放在栈上的,并通过相对栈顶(%rsp)的偏移量来访问。

 
图3.8栈

3.3.2赋值
hello.c中只有一处赋值,就是在for循环中对i赋初值0

 
图3.9赋值源

在前面我们已经确定i存在-4(%rbp)中,查找代码得知

 
图3.10赋值

这里是用mov指令的方式进行赋值操纵的,是直接将立即数0赋给i。而这里由于是int型的数据,是4个字节,故利用movl指令。
3.3.3算术操纵
for循环中有明显的算术操纵i++

 
图3.11算术操纵

观察是通过add指令进行的,同样由于是int型变量,以是利用的是addl
3.3.4关系操纵
共有两个关系操纵

 
图3.12关系操纵源

一个是不等于,一个是小于。在.s文件中我们能找到


图3.13关系操纵

均是通过cmp指令完成的。
3.3.5数组操纵
传进来的是数组指针*agrv,后面在调用printf函数以及atoi函数时也利用了数组中的值正在上传…重新上传取消

 
图3.14数组操纵

这里发现是将这个数组存到了栈中,调用时也是利用了数组的首地点加偏移量的方式进行的。
3.3.6控制转移
与关系操纵那里是关联的。就是通过前面的cmp判断变量的关系,然后通过jne、jle等指令进行跳转。
3.3.7函数操纵

 
图3.15函数操纵源

本代码中共计利用了五种函数调用。
观察调用函数的汇编代码

 
图3.16函数操纵

发现调用函数利用的是call指令,同时,在每次调用之前都会进行一个movl操纵,我们得知这是传参数的行为,函数的参数储存在rdi、rsi等寄存器中,返回值储存在rax寄存器中。
3.4 本章小结

本章围绕编译操纵睁开,首先先容了编译的概念和作用,之后在Linux中将hello.i编译成hello.s,并对编译后的hello.s进行分析。分析hello.c中的各个内容到汇编代码中的形式与内容。
(第32分)


第4章 汇编

4.1 汇编的概念与作用

汇编的概念: 汇编程序是指把汇编语言书写的程序翻译成与之等价的机器语言程序的翻译程序。汇编程序输入的是用汇编语言书写的源程序,输出的是用机器语言表现的目标程序。也就是说,汇编器会把输入的汇编指令文件重新打包成可重定位目标文件,并将效果保存成.o文件。它是一个二进制文件,包含程序的指令编码。

汇编的作用: 它的作用也很明晰了,就是完成从汇编语言文件到可重定位目标文件的转化过程。

注意:这儿的汇编是指从 .s 到 .o 即编译后的文件到天生机器语言二进制程序的过程。
4.2 在Ubuntu下汇编的命令

gcc hello.s -c -o hello.o

 
图4.1汇编命令

以下格式自行编排,编辑时删除
应截图,展示汇编过程!
4.3 可重定位目标elf格式

      
4.3.1ELF头
利用readelf -h hello.o查看elf头

 
图4.2ELF头

以一个 16B 的大小的magic 数字开头,这个数描述了该文件的系统的字的大小和字节顺序。剩下的部分包含帮助链接器语法分析息争释目标文件的信息,包括 ELF 头的大小、目标文件的范例、机器范例、节头部表的文件偏移,以及节头部表中条目标大小和数目等信息。
4.3.2查看节点头(section head)
利用readelf -S hello.o指令查看节点头

 
4.3节点头

其中ELF头和节头之间是各种节点。
其中
名称
内容含义
.text
已编译程序的机器代码
.rodata
制度数据
.data
已初始化的全局和静态C变量
.bss
未初始化的全局和静态C变量以及全部被初始化为零的全局和静态变量
.rel.data
被模块引用或定义的全部全局变量的重定位信息
.rel.text
一个.tex节中位置的列表
.symtab
一个符号表
.strtab
一个字符串表
.line
原始C中的行号和.text中的映射
.debug
一个调试符号表

4.3.3查看符号表
利用readelf -s hello.o查看符号表

 
图4.4符号表

其中,name是符号名称、value是符号相对起始位置的偏移量、type是范例,标志符号是数据还是函数、bind表明符号是局部的还是全局的、Size表明目标大小。Ndx该字段是一个到节头部表的索引,表明对应符号被分配至目标文件的某个节;其中有三个特殊的伪节,他们在节头部表中是没有条目标:ABS代表不应被重定位的符号,und代表未被定义的符号,即引用的外部符号。
4.3.4 可重定位段信息
利用readelf -r hello.o

 
图4.5可重定位段

其中偏移量是须要被修改的引用的节偏移量,符号值标识被修改引用应该指向的符号。范例分为两种一种是R_X86_64_32(重定位一个利用32位PC相对地点的引用。通过绝对寻址,CPU直接利用在指令中编码的32位值作为有效地点,不须要进一步修改。)和R_X86_64_PLT32(重定位一个利用32位PC相对地点的引用。通过绝对寻址,CPU直接利用在指令中编码的32位值作为有效地点,不须要进一步修改。)两种,作用是告知毗连器怎样修改新的引用,而加数是一个有符号常数,一些范例的重定位要利用它对被修改的引用的值做偏移调解。
    分析hello.o的ELF格式,用readelf等列出其各节的基本信息,特殊是重定位项目分析。
4.4 Hello.o的效果解析

       利用objdump -d hello.o>hello_asm.txt指令将.o文件反汇编,将效果输出到txt文件中这是反汇编的效果
  

 
图4.6反汇编代码

       这是一串反汇编的代码与.s文件中的代码十分相似。差别的是在这个txt内容中的左边有着一串十六进制的代码,这是右边对应的汇编语言的机器语言代码。这些机器代码是二进制机器指令的聚集,每一条机器代码都对应一条机器指令,到这儿才是机器真正能辨认的语言。每一条汇编语言都可以用机器二进制数据来表现,汇编语言中的操纵码和操纵数以一种相当于映射的方式和机器语言进行对应,从而让机器能够真正理解代码的含义并且执行相应的功能。
       同时在分支转移函数调用时,在汇编语言内容中利用的是跳转到标识符,而在汇编语言中则是直接指明了跳转的地点。同时在汇编语言中立即数是十进制显示的、而在反汇编代码中是利用16进制。
objdump -d -r hello.o  分析hello.o的反汇编,并请与第3章的 hello.s进行对照分析。
分析机器语言的构成,与汇编语言的映射关系。特殊是机器语言中的操纵数与汇编语言不一致,特殊是分支转移函数调用等。
4.5 本章小结

本章首先先容了汇编的概念和作用,接着通过实操,对hello.s文件进行汇编,天生ELF可重定位目标文件hello.o,接着利用readelf工具,通过设置差别参数,查看了hello.o的ELF头、节头表、可重定位信息和符号表等,通过分析理解可重定位目标文件的内容。最后将其与hello.s比较,分析差别,并分析机器语言与汇编语言的逐一对应关系。
(第41分)


第5章 链接

5.1 链接的概念与作用

概念:指将各种代码和数据片段收集并组合称为一个单一文件的过程,这个文 件可以被加载到内存并执行。链接可以执行与编译时,也可以执行于加载时,还 可以执行于运行时。
作用:将差别功能的片段组合在一起,形成一个能执行完备功能的程序。链接 的存在可以使得分离编译成为可能。这样就可以不用将一个大型的应用程序构成 一个巨大的源文件,而是将其分解成更小、更好管理的模块。可以通过独立修改 这些模块实现功能的改变。
5.2 在Ubuntu下链接的命令

命令:ld -o hello -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o hello.o /usr/lib/x86_64-linux-gnu/libc.so /usr/lib/x86_64-linux-gnu/crtn.o

 
图5.1链接命令



 
图5.2天生文件


利用指令竣事之后天生hello的可执行文件。

利用ld的链接命令,应截图,展示汇编过程! 注意不只毗连hello.o文件
5.3 可执行目标文件hello的格式

包括各段的起始地点,大小等信息。

 
图5.3ELF头


type范例为exec表明hello是一个可执行目标文件,由之前的14个section变为如今的27个section
输入readelf -S hello可以看到节头sectionheaders的具体信息

 
图5.4节点头

Section Headers:节头部表,记录各节名称、范例、地点、偏移量、大小、全体大小、旗标、链接、信息、对齐。 因此根据 Section Headers 中的信息我们就可以用 HexEdit 定位各个节所占的区间(起始位置,大小)。其中地点是程序被载入到虚拟地点的起始地点。
输入指令readelf -s hello可以看到hello.elf中Symbol table的具体信息,效果如下:

 
图5.5符号表


    分析hello的ELF格式,用readelf等列出其各段的基本信息,包括各段的起始地点,大小等信息。
5.4 hello的虚拟地点空间


 
图5.6程序头


观察程序头:分析程序头LOAD可加载的程序段的地点为0x400000
从edb打开hello从Data Dump窗口观察hello加载到虚拟地点的状态
edb界面如下

 
图5.7EDB窗口


具体观察data dump窗口

 

 
图5.8、5.9DATADUMP


发现虚拟地点从0x400000到0x401ff0竣事。根据的节头部表,可以通过edb找到各个节的信息。
利用edb加载hello,查看本进程的虚拟地点空间各段信息,并与5.3对照分析分析。
5.5 链接的重定位过程分析


 
图5.9重定位指令


利用objdump -d -r hello指令得到hello的反汇编文件。发现与hello,o文件的反汇编有所差别
1.节的数目
与hello.o的反汇编文件对比发现,hello_asm1.txt中多了许多节。
hello_asm.txt中只有一个.text节,而且只有一个main函数,函数地点也是默认的0x000000.
hello_asm1.txt中有.init,.plt,.text三个节,而且每个节中有很多函数。库函数的代码都已经链接到了程序中,程序各个节变的更加完备,跳转的地点也具有参考性。
如图


 
图5.10各种信息


明显后来生辰的这个反汇编文件中多了几个节
这些节分别是
hello比hello.o多出的节头表:
.interp 保存ld.so的路径
.note.ABI.tag Linux下特有的section
.note.gnu.build-i 编译信息表
.gnu.hash gnu的扩展符号hash表
.dynsym 动态符号表
.dynstr 动态符号表中的符号名称
.gnu.version 符号版本
.gnu.version_r 符号引用版本
.rela.dyn 动态重定位表
.rela.plt .plt节的重定位条目
.init 程序初始化
.plt 动态链接表
.fini 程序终止时须要的执行的指令
.eh_frame 程序执行错误时的指令
.dynamic 存放被ld.so利用的动态链接信息
.got 存放程序中变量全局偏移量
.got.plt 存放程序中函数的全局偏移量
.data 初始化过的全局变量大概声明过的函数
2.内容差异
hello_asm.txt中虚拟地点没有明确,均为0,没有完成可重定位的过程

图5.11section


而在hello_asm1.txt中

 
图5.12hello_asm1.tx

都有了明确的虚拟地点,分析已经完成了重定位。
重定位就是把程序的逻辑地点空间变更成内存中的实际物理地点空间的过程。它是实现多道程序在内存中同时运行的基础。重定位有两种,分别是动态重定位与静态重定位。
hello重定位的过程:
(1)重定位节和符号定义链接器将全部范例相同的节归并在一起后,这个节就作为可执行目标文件的节。然后链接器把运行时的内存地点赋给新的聚合节,赋给输入模块定义的每个节,以及赋给输入模块定义的每个符号,当这一步完成时,程序中每条指令和全局变量都有唯一运行时的地点。
(2)重定位节中的符号引用这一步中,毗连器修改代码节和数据节中对每个符号的引用,使他们指向正确的运行时地点。执行这一步,链接器依靠于可重定位目标模块中称为的重定位条目标数据布局。
(3)重定位条目当编译器遇到对最终位置未知的目标引用时,它就会天生一个重定位条目。利用在.rela.data和.rela.txt节中保存的重定位信息,来修改对各个符号的引用,即修改他们的地点。
!!!
objdump -d -r hello 分析hello与hello.o的差别,分析链接的过程。
联合hello.o的重定位项目,分析hello中对其怎么重定位的。
5.6 hello的执行流程

1.开始执行:startlibc_start_main
2.执行main:mainprintf、exitsleep、_getchar
3.退出:exit
程序名及地点:
_start 0x4010f0
_libc_start_main 0x2f12271d
main 0x401125
_printf 0x401040
_exit 0x401070
_sleep 0x401080
_getchar 0x401050
利用edb执行hello,分析从加载hello到_start,到call main,以及程序终止的全部过程。请列出其调用与跳转的各个子程序名或程序地点。
5.7 Hello的动态链接分析

动态链接的基本思想是把程序按照模块拆分成各个相对独立部分,在程序运行时才将它们链接在一起形成一个完成的程序,而不是像静态链接一样把全部程序模块都链接成一个单独的可执行文件。在调用共享库函数时,编译器没有办法预测这个函数的运行时地点,由于定义它的共享模块在运行时可以加载到恣意位置。正常的方法是为该引用天生一条重定位记录,然后动态链接器在程序加载的时间再解析它。
在进行动态链接前,首先要进行静态链接,天生部分链接的可执行目标文件hello。动态链接接纳了耽误加载的策略,即在调用函数时才进行符号的映射。利用偏移量表got+过程链接表plt实现函数的动态链接。got中存放函数目标地点,为每个全局函数创建一个副本函数,并将对函数的调用转换成对副本函数调用。.got全局偏移表 .plt程序链接表
观察elf文件中.got的起始位置

 
图5.13elf中Got


为0x403ff0
在edb中查看

 
图5.14edb查询


发如今调用dl_init之前的0x403ff0后的16个字节均为0

 
图5.15调用后内容

在调用之后发现,发生了变革存入了地点。

5.8 本章小结

本章首先先容了链接的概念和作用,详细分析了可执行目标文件的布局,及重定位过程。并且以可执行目标文件hello为例,具体分析了各个段、重定位过程、虚拟地点空间、执行流程等。
(第51分)



第6章 hello进程管理

6.1 进程的概念与作用

 
进程的经典定义就是一个执行中程序的实例。系统中的每个程序都运行在某个进程的上下文中。通过进程的概念提供给我们一个假象,就好像我们的程序是系统中运行的唯一的程序;程序好像独占地利用处理器和内存;处理器好像是无间断地一条接一条地执行程序中的指令;程序的代码和数据好像是系统内存中唯一的对象。



其中上下文是由程序正确运行所需的状态构成的,包括存放在内存中的程序的代码和数据,它的栈,通用目标寄存器的内容,程序计数器,环境变量以及打开文件描述符的聚集。

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

shell是指为利用者提供操纵界面的软件,是一个交互型应用级程序,它接收用户命令,然后调用相应的应用程序。shell是系统的用户界面,提供了用户与内核进行交互操纵的接口。

shell的作用:shell最告急的功能是命令解释,可以说shell是一个命令解释器。Linux系统上的全部可执行文件都可以作为shell命令来执行,同时它也提供一些内置命令。此外,shell还包括通配符、命令补全、命令历史、重定向、管道、命令替换等很多功能。

shell的处理流程:
①从终端读入输入的命令。

②将输入字符串切分获得全部的参数。

③检查第一个命令行参数是否是一个内置的shell命令,假如是则立即执行。

④假如不是内部命令,调用fork( )创建新进程/子进程执行指定程序。

⑤shell应该担当键盘输入信号,并对这些信号进行相应处理。
6.3 Hello的fork进程创建过程

进程的创建接纳fork函数:pid_t fork(void);创建的子进程得到与父进程用户级虚拟地点空间相同的(但是独立的)一份副本,包括代码和数据段、堆、共享库以及用户栈。子进程还获得与父进程任何打开文件描述符相同的副本,这就意味着当父进程fork时,子进程可以读取父进程中打开的任何文件。

父进程与创建的子进程之间最大的区别在于它们有差别的PID。子进程中,fork返回0。由于子进程的PID总是为非零,返回值就提供一个明确的方法分辨程序是在父进程还是在子进程中。
在终端中输入命令行./hello 2021112608 贺荣奇 1后,首先shell对我们输入的命令进行解析,由于我们输入的命令不是一个内置的shell命令,因此shell会调用fork()创建一个子进程,子进程几乎但不完全与父进程相同。通过fork函数,子进程得到与父进程用户级虚拟地点空间相同的但是独立的一份副本,拥有差别的PID。
6.4 Hello的execve过程

execve函数在当前进程的上下文中加载并运行一个新程序,原型为
:int execve(const char *filename, const char *argv[], const char *envp[])
程序会加载运行可执行文件filename,而且是带着参数列表argv和环境变量列表envp,当然在错误的时间会返回(也仅在错误时返回),大概是在没有找到filename时会返回。以是,execve()函数调用一次且不会返回。
execve函数加载可执行文件,创建一组新的代码、数据、堆栈,设置pc指向_start的地点并调用main函数。
6.5 Hello的进程执行

       进程提供给程序的抽象:

  • 独立的逻辑控制流,造成一种进程自己利用逻辑控制流的假象。
  • 独立的地点空间,造成进程认为地点空间被他独占的假象
       上下文信息:操纵系统利用上下文切换的非常控制流来实现多任务。上下文分为用户级上下文和系统级上下文。每个进程的虚拟空间地点和进程自己逐一对应,也就意味着这个上下文着实就是进程能够正常运作所需的一堆状态。如堆栈数据等这些都存放在虚拟地点空间中,由于CPU仅仅只能同时处理一个程序,然而实际环境中,我们并不满足于只做一个工作,以是我们利用上下文切换的方法,实现一种瓜代式的并行操纵。
       进程时间片:书接上文,着实就是在这一时间段内是由这个进程执行的一个时间段就交做一个时间片。
       内核模式与用户模式:处理器利用一个寄存器的一个模式位来设置一个应用可以执行的指令的权限和访问地点空间的限定。
hello进程执行过程:
开始运行在用户模式,当调用sleep后陷入内核模式,内核处理休眠请求释放该进程,将其移入等待序列中,当休眠时间竣事后会发送给内核一个中断信号,内核进行中断处理,将hello从等待序列中移除,就绪后hello就可以继续执行了。

联合进程上下文信息、进程时间片,阐述进程调理的过程,用户态与核心态转换等等。
6.6 hello的非常与信号处理

非常种别
非常种别
       处理方式
中断
收到i/o信号
读取非常号,调用中断处理程序,返回下一条指令
陷阱
Hello的父进程执行syscall指令fork一个hello
陷阱处理程序在内核态中完成fork工作,返回syscall之后的指令
故障
缺页非常
从磁盘中加载得当页,然后重新加载指令
终止
出现DRAM或SRAM位损坏的奇偶错误
Abort例程终止改程序


6.6.1乱按:

 
图6.1乱按

可以发现乱按并不会影响程序正常运行。
6.6.2回车:

 
图6.2回车

由图中得知,回车也不会影响进程工作。
6.6.3 Ctrl-Z:

 
图6.3C+Z

发现按下Ctrl+Z后程序制止。并显示:已制止
此时我们输入ps:

图6.4查看ps

发现hello着实还在进程列表中。
我们再输入jobs

 
图6.5查看jobs

显示如上
输入pstree:

 
图6.6查看pstree

综上内容,我们得出结论,ctrl+z后程序固然提示已制止,着实并没有终止,而是相当于挂在了背景。
输入kill 4330

 
图6.7 kill

6.6.4 Ctrl+C:

 
图6.8C+C

没有显示已制止但是退出了程序。
查看ps后发现背景并没有hello分析已经终止。
hello执行过程中会出现哪几类非常,会产生哪些信号,又怎么处理的。
 程序运行过程中可以按键盘,如不绝乱按,包括回车,Ctrl-Z,Ctrl-C等,Ctrl-z后可以运行ps  jobs  pstree  fg  kill 等命令,请分别给出各命令及运行结截屏,分析非常与信号的处理。
6.7本章小结

本章先容了进程的概念和作用,以及壳Shell-bash的作用与处理流程,调用 fork 创建新进程,调用 execve函数执行 hello,最后先容了执行过程中的非常与信号处理。
(第61分)


第7章 hello的存储管理

7.1 hello的存储器地点空间

我们首先分析分析逻辑地点、线性地点、虚拟地点、物理地点的概念。
逻辑地点:由程序产生的段偏移地点。它由一个段标识符和一个段偏移量构成。利用段标识符作为GDT/LDT的下标,查询表格以获得段地点。分段地点+末端偏移量=线性地点
线性地点:一个有序的非负整数地点集。假如这时的地点是一连的,就说这个空间是一个线性地点空间。它是逻辑地点向物理地点转化过程中的一步。
虚拟地点:在掩护模式下,程序在虚拟内存中运行。虚拟内存被构造成一个存储在磁盘上的N个一连的字节大小的单元阵列。每个字节都有一个唯一的虚拟地点,作为数组的索引。虚拟地点由VPO(虚拟页偏移)、VPN(虚拟页号)、TLBI(TLB索引)和TLBT(TLB标签)构成。
物理地点:计算机系统的主存储器被构造成一个由M个一连的字节大小的单元构成的阵列,每个字节有一个唯一的物理地点,比方,第一个字节地点是0,第二个地点是1,以此类推。物理地点空间对应于系统中的M个字节的物理内存。{0,1,2......M-1}.
联合hello分析逻辑地点、线性地点、虚拟地点、物理地点的概念。
7.2 Intel逻辑地点到线性地点的变更-段式管理

一个逻辑地点由两部分构成:段标识符,段内偏移量。段标识符是一个16位的字段,被称为段选择符。其中前13位是一个索引号。可以通过段标识符的索引号,直接在段描述符表中找到一个具体的段描述符,这个描述符就描述了一个段。很多个段描述符,就组了一个数组,叫“段描述符表”,可以通过段标识符的前13位,直接在段描述符表中找到一个具体的段描述符。每一个段描述符由8个字节构成。
Base字段,它描述了一个段的开始位置的线性地点。Intel设计的本意是,一些全局的段描述符,就放在“全局段描述符表”中,一些局部的,比方每个进程自己的,就放在所谓的“局部段描述符表”中,用段选择符中的T1字段来判断用全局段描述符表还是局部段描述符表,=0,表现用全局段描述符表,=1,表现用局部段描述符表。
给定一个完备的逻辑地点段选择符+段内偏移地点,看段选择符的T1为0还是1,知道当前要转换是GDT中的段,还是LDT中的段,再根据相应寄存器,得到其地点和大小。利用段选择符中的前13位,在这个数组中查找到对应的段描述符,即可得到它的基地点,基地点Base + offset即要转换的线性地点。
7.3 Hello的线性地点到物理地点的变更-页式管理

线性地点即虚拟内存(VA)到物理地点(PA)之间的转换通过分页机制完成,而分页机制是对虚拟空间进行分页。
操纵系统将虚拟页作数据传输的基本单元,linux下每个虚拟页大小为4kb,物理内存也被分割为物理页,MMU负责翻译,能够将虚拟地点映射到物理地点。
虚拟地点(n位)包括两个部分:一个p位的虚拟页内偏移(VPO VIRTURAL PAGE OFFSET)和n-p位虚拟页号(VPN),MMU利用VPN选择得当的PTE根据PTE我们得知虚拟页的信息,假如樊村了,就将页表中对应的物理页号与VPO毗连起来就是一个物理地点,假如为缓存那么将导致一个缺页故障,详见第六章。
7.4 TLB与四级页表支持下的VA到PA的变更

每次CPU产生一个虚拟地点,MMU就要查阅PTE,很慢!我们整了一个TLB快表来改善。TLB通过虚拟地点VPN部分进行以是,分为索引TLBI和标志TLBT两个部分。这样MMU直接读取PTE,不命中时再将PTE中的复制到TLB中,相当于多了一级。
7.5 三级Cache支持下的物理内存访问

获得物理地点之后,先取出组索引对应位,在L1中探求对应组。假如存在,则比较标志位,相等后检查有效位是否为1.假如都满足则命中取出值传给CPU,否则按顺序对L2cache、L3cache、内存进行相同操纵,直到出现命中。然后再一级一级向上传,假如有空闲块则将目标块放置到空闲块中,否则将缓存中的某个块驱逐,将目标块放到被驱逐块的位置。
7.6 hello进程fork时的内存映射

Shell通过调用fork()函数自动创建一个新的进程,这个进程有新的数据布局,并且内核给他分配了一个唯一的pid。同时有着自己的独立的虚拟内存空间,独立的逻辑控制流,除此以外还有与父进程相同的地区布局、页表等的一份副本,也可以访问任何父进程已经打开的文件。
当fork在新进程中返回时,新进程如今的虚拟内存刚好和调用fork时存在的虚拟内存相同,当这两个进程中的任一个后来进行写操纵时,写时复制机制就会创建新页面,因此,也就为每个进程保持了私有地点空间。
7.7 hello进程execve时的内存映射

在bash中的进程中执行了如下的execve调用:execve("hello",NULL,NULL);execve函数在当前进程中加载并运行包含在可执行文件hello中的程序,用hello替换当前bash中的程序。删除已存在的用户地区,然后映射私有地区,映射共享地区,为了设置程序计数器,最后要用exceve设置当前进程的上下文中的程序计数器到代码地区的入口点。

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

假如程序执行过程中发生了缺页故障,则内核会调用缺页处理程序。程序首先会检查虚拟地点是否合法,假如不合法则触发一个段错误,将程序终止。然后检查进程是否有读、写或执行该地区页的权限,假如不具有则触发掩护非常,程序终止。两步检查都无误后,内核将选择一个牺牲页,假如该页被修改过则将其交换出去,换入新的页并更新页表。然后将控制转移给hello进程,再次执行触发缺页故障的指令。
7.9动态存储分配管理

全部动态申请的内存都存在堆上面,用户通过保存在栈上面的一个指针来利用该内存空间。动态内存分配器维护着堆,堆顶指针是brk。有两种风格,一种叫显式分配器,利用两个函数,malloc和free,分别用于执行动态内存分配和释放。
malloc的作用是向系统申请分配堆中指定size个字节的内存空间。也就是说函数返回的指针为指向堆里的一块内存。并且,操纵系统中有一个记录空闲内存地点的链表。当操纵系统收到程序申请时,就会遍历该链表,然后探求第一个空间大于所申请空间的堆结点,将该结点从空闲结点链表中删除后,将该结点的空间分配给到程序。在利用malloc()分配内存空间后,需释放内存空间,否则就会出现内存泄漏。
free()释放的是指针指向的内存,而不是指针。指针并没有被释放,它仍然指向原来的存储空间。因此指针须要手动释放,指针是一个变量,只有当程序竣事时才被烧毁。释放了内存空间后,原本指向这块空间的指针仍然存在。但此时指针指向的内容为垃圾,是未定义的。因此,释放内存后要把指针指向NULL,防止该指针后续被解引用。
7.10本章小结

本章主题是hello的存储管理,在差别空间中有着差别的地点,虚拟空间中是虚拟地点,在物理空间中是物理地点。程序利用逻辑地点,在操纵系统中进行两种地点的转换来利用,同时分析了hello的内存映射、缺页故障与缺页中断处理和动态存储分配管理等。
(第7 2分)


第8章 hello的IO管理

8.1 Linux的IO装备管理方法

装备的模型化:全部IO装备都被模型化为文件,全部的输入和输出都能被当做相应文件的读和写来执行。
装备管理:Linux内核有一个简单、低级的接口,成为Unix I/O,是的全部的输入和输出都能以一种统一且一致的方式来执行。
8.2 简述Unix IO接口及其函数

Unix I/O接口:

1.打开文件。一个应用程序通过要求内核打开相应的文件,来宣告它想 要访问一个 I/O 装备

 2.shell 创建的每个进程开始时都有三个打开的文件:标准输入(描述符为0)、标准输出(描述符为1)和标准错误(描述符为2)。

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

4. 读写文件。一个读操纵就是从文件复制n>0个字节到内存,从当前文件位置k开始,然后将k增长到k+n,给定一个大小为m字节的而文件,当k>=m时,触发EOF。雷同一个写操纵就是从内存中复制n>0个字节到一个文件,从当前文件位置k开始,然后更新k。

5. 关闭文件。当应用完成了对文件的访问之后,它就关照内核关闭这个文件,作为响应,内核释放文件打开时创建的数据布局,并将这个描述符恢复到可用的描述符池中。无论一个进程由于何种原因终止时,内核都会关闭全部打开的文件并释放他们的内存资源。
Unix I/O函数:

1.打开文件:int open(char* filename,int flags,mode_t mode)

Filename:文件名

Flags:文件权限

Mode:指定新文件的访问权限位

返回值:成功则返回文件描述符,失败则返回-1.

2.关闭文件:int close(int fd)

Fd:文件描述符

返回值:成功则返回0,失败则返回-1

3.读文件ssize_t read(int fd,void *buf,size_t n)

Buf:存储要写的数据

n:写入的长度,单元:字节

返回值:成功则返回写入的字节数,失败则返回-1。

4.写文件ssize_t wirte(int fd,const void *buf,size_t n)

Buf:存储要写的数据

n:读出的长度,单元:字节

返回值:成功则返回读出的字节数,失败则返回-1。
8.3 printf的实现分析


 
图8.1printf源码

printf程序按照格式fmt联合参数args天生格式化之后的字符串,并返回字串的长度。printf用了两个外部函数,一个是vsprintf,还有一个是write。
vsprintf函数作用是担当确定输特别式的格式字符串fmt(输入)。用格式字符串对个数变革的参数进行格式化,产生格式化输出。
write函数将buf中的i个元素写到终端。
从vsprintf天生显示信息,到write系统函数,到陷阱-系统调用 int 0x80或syscall等.
字符显示驱动子程序:从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)。
显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量)。
8.4 getchar的实现分析

getchar代码部分:

int getchar(void)

{

static char buf[BUFSIZ];

static char* bb=buf;

static int n=0;

if(n==0)

{

n=read(0,buf,BUFSIZ);

bb=buf;

}

return (–n>=0)?(unsigned char)*bb++:EOF;

}

当利用getchar时,程序发生陷阱的非常。当按键盘时会产生中断。

异步非常-键盘中断的处理:键盘中断处理子程序。担当按键扫描码转成ascii码,保存到系统的键盘缓冲区。

getchar等调用read系统函数,通过系统调用读取按键ascii码,直到担当到回车键才返回。
异步非常-键盘中断的处理:键盘中断处理子程序。担当按键扫描码转成ascii码,保存到系统的键盘缓冲区。
getchar等调用read系统函数,通过系统调用读取按键ascii码,直到担当到回车键才返回。
8.5本章小结

本章主要先容了Linux的IO装备管理方法、Unix IO接口及其函数,分析了printf和getchar函数的实现。
(第81分)

结论

hello所经历的过程:

  • 通过编辑器编写形成最初的.c文件,是hello的源程序。
  • 利用预处理器cpp将.c文件预处理形成.i文件
  • 利用编译器ccl将其进行翻译天生汇编语言文件.o文件
  • 利用汇编器将其翻译成一个可重定位目标文件hello.o
  • 利用毗连器程序ld将hello.o与系统目标文件联合起来,创建了一个可执行文件hello。
  • 运行hello程序
  • 通过shell输入./hello,shell通过fork函数创建了一个新的进程,之后调用execve映射虚拟内存,通过mmap为hello程序开创了一片空间。
  • CPU从虚拟内存中的.text,.data节取代码和数据,调理器为进程规划时间片,有非常时触发非常处理子程序。
  • 程序运行竣事时,父进程接纳hello进程和它创建的子进程,内核删除相关数据布局。
深切感悟:
从大一开始学习C语言,每一个操纵都看似不难,编译指令仅仅只须要我们按一下编译按钮,这个按钮的背后是复杂的指令是前辈聪明的结晶!我要学习的东西还很多,要继续加油继续积极!

(结论0分,缺失 -1分,根据内容酌情加分)


附件

文件名
作用
Hello.c
源程序
Hello.i
预处理后的文件
Hello.s
汇编文件
Hello.o
可重定位目标执行文件
Hello
可执行文件
Hello.elf
Hello.o的elf文件
Hello_asm.txt
Hello.o的反汇编
Hello1_asm.txt
Hello的反汇编
Hello1.elf
Hello的elf

列出全部的中心产物的文件名,并予以分析起作用。
(附件0分,缺失 -1分)


参考文献


[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.
(参考文献0分,缺失 -1分)



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

种地

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表