摘  要

本文分析Hello程序的全生命周期,首先编写hello.c的源程序,然后运行C预处理器进行预处理,创建hello.i文件,运行C编译器。翻译生成汇编语言文件hello.s,然后运行汇编器,翻译成移动的目标文件hello.o,最后运行链接器程序ld把hello.o和系统目标文件一起包含进来创建文件hello可执行文件。当 shell 收到 ./hello 命令时,它会启动一个 fork 函数来创建一个 execve 进程,将 hello 加载到内存中,控制 CPU 中断,切换上下文,以及处理流异常。程序逻辑,最后,结束进程,由父进程回收。hello“生命”的终结

关键词:预处理编译汇编;链接;进程;IO管理;存储; 

目  录

第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语言代码,作为程序保存为hello.c,然后在shell中接受预处理、编译、汇编、链接后的可执行文件。在shell中./hello创建进程,加载可执行文件以运行 hello 程序(即产生 hello 进程)

020:Shell 为 Hello 创建一个进程。并加载Hello可执行程序,映射虚拟内存,进入程序列表,将程序加载到物理内存,main函数运行目标代码,CPU分配运行时间。 Hello执行逻辑控制流程,最后Hello正常退出或收到信号后终止。这将导致操作系统停止Hello进程,释放它所占用的所有资源,并返回给Shell,这是一个从无(0)到无(0)的Hello进程。

1.2 环境与工具

硬件环境:

系统:windows10、Ubuntu 20

工具:g++,vim,edb,vscode,objdump

1.3 中间结果

hello.c:C语言源程序

hello.i:hello.c预处理的文本文件

hello.s:hello.i编译后的汇编文件

hello.o:hello.s汇编后的可重定位(relocatable)文件

hello.o.elf.txt:hello.o经过readelf得到的文本文件

hello:可执行文件

hello.elf.txt:hello经readelf得到的文本文件

hello.o.s:hello.o经objdump得到的汇编代码

hello.oo:hello.oo经objdump得到的汇编代码

1.4 本章小结

本章简单介绍了Hello程序的一生,并勾勒出从P2P到020的整个过程。发现学习整个计算机系统与Hello的一生基本相同。 关于实验软硬件环境和采集处理工具,这就是文章的大致大纲

第2章 预处理

2.1 预处理的概念与作用

概念:预处理器根据以字符“#”开头的命令处理hello.c源程序。

作用:根据源代码中的预处理指令修改源代码,将系统头文件中的头文件源代码插入到目标文件中,最终生成hello.i文件

2.2在Ubuntu下预处理的命令

g++ -E -o hello.i hello.c

2.3 Hello的预处理结果解析

行数显著增多且原本的main()在结尾,g++将#include引入的头文件进行了展开

2.4 本章小结

本章简要介绍了预处理的概念和功能。 并对Linux系统下的hello.c文件进行预处理。 从解析出来的hello.i文件可以看出,预处理操作对源文件中包含的头文件进行了扩展和扩展。 并进行其他处理,如替换指定的宏符号,并按指示选择性地编译。

第3章 编译

3.1 编译的概念与作用

概念:编辑器将文本文件hello.i转化为文本文件hello.s,即一个汇编语言程序。

作用:把源程序翻译成目标程序,进行词法分析和语法分析,分析过程中发现有语法错误,给出提示信息。

3.2 在Ubuntu下编译的命令

g++ hello.i -S -o hello.s

3.3 Hello的编译结果解析

3.3.1 文件开头

.file:源文件名

.text:代码段

.rodata:只读数据段

.globl:全局符号

.type:符号main为函数

.string:字符串

.align:对齐方式

以下格式自行编排,编辑时删除

3.3.2 数据保存

字符串:6行8行即为两个字符串,都保存在只读数据部分

局部变量:main中声明了局部变量i,保存在栈上

main()的参数argv:保存在栈上

常数(汇编中的立即数):写在汇编指令中

3.3.3 mov指令

移动数据

有movl和movq两种不同长度的mov指令出现

3.3.4 加法

类似的用到了addl,addq

3.3.5 条件

汇编中通过cmp、jmp类(jg)指令实现条件操作

3.3.6 调用函数

Call指令

多次出现在调用各个库函数时

3.4 本章小结

本章提供对汇编指令的简要介绍以及对 Hello 的机器级实现的理解。我们可以找到这些汇编指令与C语言代码语句的对应关系。 同时,根据一个程序的汇编代码,我们也可以还原出相应的C语言程序的大致样子。

第4章 汇编

4.1 汇编的概念与作用

汇编的概念:汇编是指将用汇编语言编写的程序翻译成等效的机器语言程序的翻译器。汇编器输入用汇编语言编写的源程序,输出以机器语言显示的程序对象,即汇编器将输入的汇编命令文件重新打包成可移动的目标文件并将结果保存为 .o 文件,它是对程序指令进行编码的二进制文件。

汇编的作用:它的作用也很明确,即执行从汇编语言文件到可重定位目标文件的转换

4.2 在Ubuntu下汇编的命令

g++ hello.s -c -o hello.o

4.3 可重定位目标elf格式

使用readelf生成elf文件信息hello.o.elf

生成结果完整内容:

ELF Header:

Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00

Class:                             ELF64

Data:                              2's complement, little endian

Version:                           1 (current)

OS/ABI:                            UNIX - System V

ABI Version:                       0

Type:                              REL (Relocatable file)

Machine:                           Advanced Micro Devices X86-64

Version:                           0x1

Entry point address:               0x0

Start of program headers:          0 (bytes into file)

Start of section headers:          1240 (bytes into file)

Flags:                             0x0

Size of this header:               64 (bytes)

Size of program headers:           0 (bytes)

Number of program headers:         0

Size of section headers:           64 (bytes)

Number of section headers:         14

Section header string table index: 13

Section Headers:

[Nr] Name              Type             Address           Offset

Size              EntSize          Flags  Link  Info  Align

[ 0]                   NULL             0000000000000000  00000000

0000000000000000  0000000000000000           0     0     0

[ 1] .text             PROGBITS         0000000000000000  00000040

0000000000000092  0000000000000000  AX       0     0     1

[ 2] .rela.text        RELA             0000000000000000  00000388

00000000000000c0  0000000000000018   I      11     1     8

[ 3] .data             PROGBITS         0000000000000000  000000d2

0000000000000000  0000000000000000  WA       0     0     1

[ 4] .bss              NOBITS           0000000000000000  000000d2

0000000000000000  0000000000000000  WA       0     0     1

[ 5] .rodata           PROGBITS         0000000000000000  000000d8

0000000000000033  0000000000000000   A       0     0     8

[ 6] .comment          PROGBITS         0000000000000000  0000010b

000000000000002c  0000000000000001  MS       0     0     1

[ 7] .note.GNU-stack   PROGBITS         0000000000000000  00000137

0000000000000000  0000000000000000           0     0     1

[ 8] .note.gnu.propert NOTE             0000000000000000  00000138

0000000000000020  0000000000000000   A       0     0     8

[ 9] .eh_frame         PROGBITS         0000000000000000  00000158

0000000000000038  0000000000000000   A       0     0     8

[10] .rela.eh_frame    RELA             0000000000000000  00000448

0000000000000018  0000000000000018   I      11     9     8

[11] .symtab           SYMTAB           0000000000000000  00000190

00000000000001b0  0000000000000018          12    10     8

[12] .strtab           STRTAB           0000000000000000  00000340

0000000000000048  0000000000000000           0     0     1

[13] .shstrtab         STRTAB           0000000000000000  00000460

0000000000000074  0000000000000000           0     0     1

Key to Flags:

W (write), A (alloc), X (execute), M (merge), S (strings), I (info),

L (link order), O (extra OS processing required), G (group), T (TLS),

C (compressed), x (unknown), o (OS specific), E (exclude),

l (large), p (processor specific)

There are no section groups in this file.

There are no program headers in this file.

There is no dynamic section in this file.

Relocation section '.rela.text' at offset 0x388 contains 8 entries:

Offset          Info           Type           Sym. Value    Sym. Name + Addend

00000000001c  000500000002 R_X86_64_PC32     0000000000000000 .rodata - 4

000000000021  000c00000004 R_X86_64_PLT32    0000000000000000 puts - 4

00000000002b  000d00000004 R_X86_64_PLT32    0000000000000000 exit - 4

000000000058  000500000002 R_X86_64_PC32     0000000000000000 .rodata + 22

000000000062  000e00000004 R_X86_64_PLT32    0000000000000000 printf - 4

000000000075  000f00000004 R_X86_64_PLT32    0000000000000000 atoi - 4

00000000007c  001000000004 R_X86_64_PLT32    0000000000000000 sleep - 4

000000000087  001100000004 R_X86_64_PLT32    0000000000000000 getchar - 4

Relocation section '.rela.eh_frame' at offset 0x448 contains 1 entry:

Offset          Info           Type           Sym. Value    Sym. Name + Addend

000000000020  000200000002 R_X86_64_PC32     0000000000000000 .text + 0

The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.

Symbol table '.symtab' contains 18 entries:

Num:    Value          Size Type    Bind   Vis      Ndx Name

0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND

1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS hello.c

2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1

3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3

4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4

5: 0000000000000000     0 SECTION LOCAL  DEFAULT    5

6: 0000000000000000     0 SECTION LOCAL  DEFAULT    7

7: 0000000000000000     0 SECTION LOCAL  DEFAULT    8

8: 0000000000000000     0 SECTION LOCAL  DEFAULT    9

9: 0000000000000000     0 SECTION LOCAL  DEFAULT    6

10: 0000000000000000   146 FUNC    GLOBAL DEFAULT    1 main

11: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND _GLOBAL_OFFSET_TABLE_

12: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND puts

13: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND exit

14: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND printf

15: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND atoi

16: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND sleep

17: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND getchar

No version information found in this file.

Displaying notes found in: .note.gnu.property

Owner                Data size       Description

GNU                  0x00000010 NT_GNU_PROPERTY_TYPE_0

Properties: x86 feature: IBT, SHSTK

对内容的分析:

1:ELF Header:以一个 16 字节的序列开头,描述了创建的文件系统的字长和字节顺序。 ELF 头的其余部分包含有助于链接器解析和解释目标文件的信息。这包括 ELF 头的大小、目标文件类型(例如重定位、可执行或共享)、机器类型(例如 x86-64)、节头表的偏移文件。以及节标题表中项目的大小和数量。部分的位置和大小它由节标题表描述。其中目标文件中的每个部分都有一个固定大小的列表。

2:节头:记录每个节的节名、类型、地址、偏移量、大小、总大小、标志、链接、数据和对齐方式。

3:重定位节:重定位节将数据保存在需要修改的.text节中(任何指令都需要修改)。调用外部函数或引用全局变量)、调用外部函数的指令以及引用全局的语句。需要修改变量搬迁调用内部函数的命令不需要移动,在 Hello 程序中,.L0 和 .L1 必须移动到 printf、put、exit、sleep、sleepseces、getchar 和 .rodata 中。

.rela.eh_frame 部分是 .eh_frame 部分的重定位数据。

4: 符号表:.symtab 是一个符号表。它存储程序中定义和引用的函数和全局变量的信息。一些程序员错误地认为编译程序需要 -g 选项来获取符号表信息。几乎所有可移动目标文件在 .symtab 中都有一个符号表

.symtab 符号表没有局部变量的条目。

4.4 Hello.o的结果解析

objdump -d -r hello.o >hello.o.s

结果:

hello.o:     file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <main>:

0:    f3 0f 1e fa               endbr64

4:    55                          push   %rbp

5:    48 89 e5               mov    %rsp,%rbp

8:    48 83 ec 20             sub    $0x20,%rsp

c:    89 7d ec               mov    %edi,-0x14(%rbp)

f:    48 89 75 e0             mov    %rsi,-0x20(%rbp)

13:    83 7d ec 04             cmpl   $0x4,-0x14(%rbp)

17:    74 16                je     2f <main+0x2f>

19:    48 8d 3d 00 00 00 00       lea    0x0(%rip),%rdi        # 20 <main+0x20>

1c: R_X86_64_PC32 .rodata-0x4

20:    e8 00 00 00 00           callq  25 <main+0x25>

21: R_X86_64_PLT32      puts-0x4

25:    bf 01 00 00 00            mov    $0x1,%edi

2a:    e8 00 00 00 00           callq  2f <main+0x2f>

2b: R_X86_64_PLT32      exit-0x4

2f:    c7 45 fc 00 00 00 00 movl   $0x0,-0x4(%rbp)

36:    83 7d fc 07              cmpl   $0x7,-0x4(%rbp)

3a:    7f 4a                  jg     86 <main+0x86>

3c:    48 8b 45 e0             mov    -0x20(%rbp),%rax

40:    48 83 c0 10             add    $0x10,%rax

44:    48 8b 10               mov    (%rax),%rdx

47:    48 8b 45 e0             mov    -0x20(%rbp),%rax

4b:    48 83 c0 08             add    $0x8,%rax

4f:    48 8b 00               mov    (%rax),%rax

52:    48 89 c6               mov    %rax,%rsi

55:    48 8d 3d 00 00 00 00       lea    0x0(%rip),%rdi        # 5c <main+0x5c>

58: R_X86_64_PC32 .rodata+0x22

5c:    b8 00 00 00 00           mov    $0x0,%eax

61:    e8 00 00 00 00           callq  66 <main+0x66>

62: R_X86_64_PLT32      printf-0x4

66:    48 8b 45 e0             mov    -0x20(%rbp),%rax

6a:    48 83 c0 18             add    $0x18,%rax

6e:    48 8b 00               mov    (%rax),%rax

71:    48 89 c7               mov    %rax,%rdi

74:    e8 00 00 00 00           callq  79 <main+0x79>

75: R_X86_64_PLT32      atoi-0x4

79:    89 c7                mov    %eax,%edi

7b:    e8 00 00 00 00           callq  80 <main+0x80>

7c: R_X86_64_PLT32      sleep-0x4

80:    83 45 fc 01              addl   $0x1,-0x4(%rbp)

84:    eb b0                jmp    36 <main+0x36>

86:    e8 00 00 00 00           callq  8b <main+0x8b>

87: R_X86_64_PLT32      getchar-0x4

8b:    b8 00 00 00 00           mov    $0x0,%eax

90:    c9                   leaveq

91:    c3                   retq

分析:

首先objdump这一指令只对指令做了处理

比较:

1

标识符替换为相对地址,.L2只是简写、易读的形式,实际汇编代码中需要替换为实际的地址

2

Call同理

4.5 本章小结

本章简要介绍了汇编的概念和功能。 展示了在linux系统下将汇编语言程序转换为可移动目标文件的过程,并详细分析了可移动目标文件的结构和内容。 以及 hello.s 中的反汇编代码和汇编代码的区别。

在本章中,可以看到汇编阶段如何将汇编语言转换为机器语言并生成重定向的目标文件。 一切都在为以后的链接做准备。 链接后会得到可执行程序hello。

第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.3 可执行目标文件hello的格式

readelf -a hello >hello.elf

完整内容如下:

ELF Header:

Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00

Class:                             ELF64

Data:                              2's complement, little endian

Version:                           1 (current)

OS/ABI:                            UNIX - System V

ABI Version:                       0

Type:                              EXEC (Executable file)

Machine:                           Advanced Micro Devices X86-64

Version:                           0x1

Entry point address:               0x4010f0

Start of program headers:          64 (bytes into file)

Start of section headers:          14208 (bytes into file)

Flags:                             0x0

Size of this header:               64 (bytes)

Size of program headers:           56 (bytes)

Number of program headers:         12

Size of section headers:           64 (bytes)

Number of section headers:         27

Section header string table index: 26

Section Headers:

[Nr] Name              Type             Address           Offset

Size              EntSize          Flags  Link  Info  Align

[ 0]                   NULL             0000000000000000  00000000

0000000000000000  0000000000000000           0     0     0

[ 1] .interp           PROGBITS         00000000004002e0  000002e0

000000000000001c  0000000000000000   A       0     0     1

[ 2] .note.gnu.propert NOTE             0000000000400300  00000300

0000000000000020  0000000000000000   A       0     0     8

[ 3] .note.ABI-tag     NOTE             0000000000400320  00000320

0000000000000020  0000000000000000   A       0     0     4

[ 4] .hash             HASH             0000000000400340  00000340

0000000000000038  0000000000000004   A       6     0     8

[ 5] .gnu.hash         GNU_HASH         0000000000400378  00000378

000000000000001c  0000000000000000   A       6     0     8

[ 6] .dynsym           DYNSYM           0000000000400398  00000398

00000000000000d8  0000000000000018   A       7     1     8

[ 7] .dynstr           STRTAB           0000000000400470  00000470

000000000000005c  0000000000000000   A       0     0     1

[ 8] .gnu.version      VERSYM           00000000004004cc  000004cc

0000000000000012  0000000000000002   A       6     0     2

[ 9] .gnu.version_r    VERNEED          00000000004004e0  000004e0

0000000000000020  0000000000000000   A       7     1     8

[10] .rela.dyn         RELA             0000000000400500  00000500

0000000000000030  0000000000000018   A       6     0     8

[11] .rela.plt         RELA             0000000000400530  00000530

0000000000000090  0000000000000018  AI       6    21     8

[12] .init             PROGBITS         0000000000401000  00001000

000000000000001b  0000000000000000  AX       0     0     4

[13] .plt              PROGBITS         0000000000401020  00001020

0000000000000070  0000000000000010  AX       0     0     16

[14] .plt.sec          PROGBITS         0000000000401090  00001090

0000000000000060  0000000000000010  AX       0     0     16

[15] .text             PROGBITS         00000000004010f0  000010f0

0000000000000145  0000000000000000  AX       0     0     16

[16] .fini             PROGBITS         0000000000401238  00001238

000000000000000d  0000000000000000  AX       0     0     4

[17] .rodata           PROGBITS         0000000000402000  00002000

000000000000003b  0000000000000000   A       0     0     8

[18] .eh_frame         PROGBITS         0000000000402040  00002040

00000000000000fc  0000000000000000   A       0     0     8

[19] .dynamic          DYNAMIC          0000000000403e50  00002e50

00000000000001a0  0000000000000010  WA       7     0     8

[20] .got              PROGBITS         0000000000403ff0  00002ff0

0000000000000010  0000000000000008  WA       0     0     8

[21] .got.plt          PROGBITS         0000000000404000  00003000

0000000000000048  0000000000000008  WA       0     0     8

[22] .data             PROGBITS         0000000000404048  00003048

0000000000000004  0000000000000000  WA       0     0     1

[23] .comment          PROGBITS         0000000000000000  0000304c

000000000000002b  0000000000000001  MS       0     0     1

[24] .symtab           SYMTAB           0000000000000000  00003078

00000000000004c8  0000000000000018          25    30     8

[25] .strtab           STRTAB           0000000000000000  00003540

0000000000000158  0000000000000000           0     0     1

[26] .shstrtab         STRTAB           0000000000000000  00003698

00000000000000e1  0000000000000000           0     0     1

Key to Flags:

W (write), A (alloc), X (execute), M (merge), S (strings), I (info),

L (link order), O (extra OS processing required), G (group), T (TLS),

C (compressed), x (unknown), o (OS specific), E (exclude),

l (large), p (processor specific)

There are no section groups in this file.

Program Headers:

Type           Offset             VirtAddr           PhysAddr

FileSiz            MemSiz              Flags  Align

PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040

0x00000000000002a0 0x00000000000002a0  R      0x8

INTERP         0x00000000000002e0 0x00000000004002e0 0x00000000004002e0

0x000000000000001c 0x000000000000001c  R      0x1

[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]

LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000

0x00000000000005c0 0x00000000000005c0  R      0x1000

LOAD           0x0000000000001000 0x0000000000401000 0x0000000000401000

0x0000000000000245 0x0000000000000245  R E    0x1000

LOAD           0x0000000000002000 0x0000000000402000 0x0000000000402000

0x000000000000013c 0x000000000000013c  R      0x1000

LOAD           0x0000000000002e50 0x0000000000403e50 0x0000000000403e50

0x00000000000001fc 0x00000000000001fc  RW     0x1000

DYNAMIC        0x0000000000002e50 0x0000000000403e50 0x0000000000403e50

0x00000000000001a0 0x00000000000001a0  RW     0x8

NOTE           0x0000000000000300 0x0000000000400300 0x0000000000400300

0x0000000000000020 0x0000000000000020  R      0x8

NOTE           0x0000000000000320 0x0000000000400320 0x0000000000400320

0x0000000000000020 0x0000000000000020  R      0x4

GNU_PROPERTY   0x0000000000000300 0x0000000000400300 0x0000000000400300

0x0000000000000020 0x0000000000000020  R      0x8

GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000

0x0000000000000000 0x0000000000000000  RW     0x10

GNU_RELRO      0x0000000000002e50 0x0000000000403e50 0x0000000000403e50

0x00000000000001b0 0x00000000000001b0  R      0x1

Section to Segment mapping:

Segment Sections...

00

01     .interp

02     .interp .note.gnu.property .note.ABI-tag .hash .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt

03     .init .plt .plt.sec .text .fini

04     .rodata .eh_frame

05     .dynamic .got .got.plt .data

06     .dynamic

07     .note.gnu.property

08     .note.ABI-tag

09     .note.gnu.property

10

11     .dynamic .got

Dynamic section at offset 0x2e50 contains 21 entries:

Tag        Type                         Name/Value

0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

0x000000000000000c (INIT)               0x401000

0x000000000000000d (FINI)               0x401238

0x0000000000000004 (HASH)               0x400340

0x000000006ffffef5 (GNU_HASH)           0x400378

0x0000000000000005 (STRTAB)             0x400470

0x0000000000000006 (SYMTAB)             0x400398

0x000000000000000a (STRSZ)              92 (bytes)

0x000000000000000b (SYMENT)             24 (bytes)

0x0000000000000015 (DEBUG)              0x0

0x0000000000000003 (PLTGOT)             0x404000

0x0000000000000002 (PLTRELSZ)           144 (bytes)

0x0000000000000014 (PLTREL)             RELA

0x0000000000000017 (JMPREL)             0x400530

0x0000000000000007 (RELA)               0x400500

0x0000000000000008 (RELASZ)             48 (bytes)

0x0000000000000009 (RELAENT)            24 (bytes)

0x000000006ffffffe (VERNEED)            0x4004e0

0x000000006fffffff (VERNEEDNUM)         1

0x000000006ffffff0 (VERSYM)             0x4004cc

0x0000000000000000 (NULL)               0x0

Relocation section '.rela.dyn' at offset 0x500 contains 2 entries:

Offset          Info           Type           Sym. Value    Sym. Name + Addend

000000403ff0  000300000006 R_X86_64_GLOB_DAT 0000000000000000 __libc_start_main@GLIBC_2.2.5 + 0

000000403ff8  000500000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0

Relocation section '.rela.plt' at offset 0x530 contains 6 entries:

Offset          Info           Type           Sym. Value    Sym. Name + Addend

000000404018  000100000007 R_X86_64_JUMP_SLO 0000000000000000 puts@GLIBC_2.2.5 + 0

000000404020  000200000007 R_X86_64_JUMP_SLO 0000000000000000 printf@GLIBC_2.2.5 + 0

000000404028  000400000007 R_X86_64_JUMP_SLO 0000000000000000 getchar@GLIBC_2.2.5 + 0

000000404030  000600000007 R_X86_64_JUMP_SLO 0000000000000000 atoi@GLIBC_2.2.5 + 0

000000404038  000700000007 R_X86_64_JUMP_SLO 0000000000000000 exit@GLIBC_2.2.5 + 0

000000404040  000800000007 R_X86_64_JUMP_SLO 0000000000000000 sleep@GLIBC_2.2.5 + 0

The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.

Symbol table '.dynsym' contains 9 entries:

Num:    Value          Size Type    Bind   Vis      Ndx Name

0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND

1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND puts@GLIBC_2.2.5 (2)

2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@GLIBC_2.2.5 (2)

3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (2)

4: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND getchar@GLIBC_2.2.5 (2)

5: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__

6: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND atoi@GLIBC_2.2.5 (2)

7: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND exit@GLIBC_2.2.5 (2)

8: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND sleep@GLIBC_2.2.5 (2)

Symbol table '.symtab' contains 51 entries:

Num:    Value          Size Type    Bind   Vis      Ndx Name

0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND

1: 00000000004002e0     0 SECTION LOCAL  DEFAULT    1

2: 0000000000400300     0 SECTION LOCAL  DEFAULT    2

3: 0000000000400320     0 SECTION LOCAL  DEFAULT    3

4: 0000000000400340     0 SECTION LOCAL  DEFAULT    4

5: 0000000000400378     0 SECTION LOCAL  DEFAULT    5

6: 0000000000400398     0 SECTION LOCAL  DEFAULT    6

7: 0000000000400470     0 SECTION LOCAL  DEFAULT    7

8: 00000000004004cc     0 SECTION LOCAL  DEFAULT    8

9: 00000000004004e0     0 SECTION LOCAL  DEFAULT    9

10: 0000000000400500     0 SECTION LOCAL  DEFAULT   10

11: 0000000000400530     0 SECTION LOCAL  DEFAULT   11

12: 0000000000401000     0 SECTION LOCAL  DEFAULT   12

13: 0000000000401020     0 SECTION LOCAL  DEFAULT   13

14: 0000000000401090     0 SECTION LOCAL  DEFAULT   14

15: 00000000004010f0     0 SECTION LOCAL  DEFAULT   15

16: 0000000000401238     0 SECTION LOCAL  DEFAULT   16

17: 0000000000402000     0 SECTION LOCAL  DEFAULT   17

18: 0000000000402040     0 SECTION LOCAL  DEFAULT   18

19: 0000000000403e50     0 SECTION LOCAL  DEFAULT   19

20: 0000000000403ff0     0 SECTION LOCAL  DEFAULT   20

21: 0000000000404000     0 SECTION LOCAL  DEFAULT   21

22: 0000000000404048     0 SECTION LOCAL  DEFAULT   22

23: 0000000000000000     0 SECTION LOCAL  DEFAULT   23

24: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS hello.c

25: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS

26: 0000000000403e50     0 NOTYPE  LOCAL  DEFAULT   19 __init_array_end

27: 0000000000403e50     0 OBJECT  LOCAL  DEFAULT   19 _DYNAMIC

28: 0000000000403e50     0 NOTYPE  LOCAL  DEFAULT   19 __init_array_start

29: 0000000000404000     0 OBJECT  LOCAL  DEFAULT   21 _GLOBAL_OFFSET_TABLE_

30: 0000000000401230     5 FUNC    GLOBAL DEFAULT   15 __libc_csu_fini

31: 0000000000404048     0 NOTYPE  WEAK   DEFAULT   22 data_start

32: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND puts@@GLIBC_2.2.5

33: 000000000040404c     0 NOTYPE  GLOBAL DEFAULT   22 _edata

34: 0000000000401238     0 FUNC    GLOBAL HIDDEN    16 _fini

35: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@@GLIBC_2.2.5

36: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_

37: 0000000000404048     0 NOTYPE  GLOBAL DEFAULT   22 __data_start

38: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND getchar@@GLIBC_2.2.5

39: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__

40: 0000000000402000     4 OBJECT  GLOBAL DEFAULT   17 _IO_stdin_used

41: 00000000004011c0   101 FUNC    GLOBAL DEFAULT   15 __libc_csu_init

42: 0000000000404050     0 NOTYPE  GLOBAL DEFAULT   22 _end

43: 0000000000401120     5 FUNC    GLOBAL HIDDEN    15 _dl_relocate_static_pie

44: 00000000004010f0    47 FUNC    GLOBAL DEFAULT   15 _start

45: 000000000040404c     0 NOTYPE  GLOBAL DEFAULT   22 __bss_start

46: 0000000000401125   146 FUNC    GLOBAL DEFAULT   15 main

47: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND atoi@@GLIBC_2.2.5

48: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND exit@@GLIBC_2.2.5

49: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND sleep@@GLIBC_2.2.5

50: 0000000000401000     0 FUNC    GLOBAL HIDDEN    12 _init

Histogram for bucket list length (total of 3 buckets):

Length  Number     % of total  Coverage

0  0          (  0.0%)

1  0          (  0.0%)      0.0%

2  1          ( 33.3%)     25.0%

3  2          ( 66.7%)    100.0%

Version symbols section '.gnu.version' contains 9 entries:

Addr: 0x00000000004004cc  Offset: 0x0004cc  Link: 6 (.dynsym)

000:   0 (*local*)       2 (GLIBC_2.2.5)   2 (GLIBC_2.2.5)   2 (GLIBC_2.2.5)

004:   2 (GLIBC_2.2.5)   0 (*local*)       2 (GLIBC_2.2.5)   2 (GLIBC_2.2.5)

008:   2 (GLIBC_2.2.5)

Version needs section '.gnu.version_r' contains 1 entry:

Addr: 0x00000000004004e0  Offset: 0x0004e0  Link: 7 (.dynstr)

000000: Version: 1  File: libc.so.6  Cnt: 1

0x0010:   Name: GLIBC_2.2.5  Flags: none  Version: 2

Displaying notes found in: .note.gnu.property

Owner                Data size       Description

GNU                  0x00000010 NT_GNU_PROPERTY_TYPE_0

Properties: x86 feature: IBT, SHSTK

Displaying notes found in: .note.ABI-tag

Owner                Data size       Description

GNU                  0x00000010 NT_GNU_ABI_TAG (ABI version tag)

OS: Linux, ABI: 3.2.0

分析

1 ELF header中,Type发生了变化,从REL变成了EXEC,节头部数量变为27个。

2 注意到链接后符号表中的符号数量迅速增加。 表示其他库函数的许多符号链接在一起并添加到符号表中后会被使用。

5.4 hello的虚拟地址空间

从40100开始

5.3中LOAD对应的地址与此相符

5.5 链接的重定位过程分析

objdump -d -r hello >hello.oo

1

不同于hello.o只有main,hello中有各个调用到的函数

链接前这些函数在库中,而链接后引入的可执行文件中

Hello的重定位过程:

1:重定位段和符号定义在链接器将相同类型的所有部分合并在一起之后。此部分成为可执行目标文件的一部分。链接器为新连接分配一个运行时内存地址到输入模块定义的每个部分,并赋予输入模块分配的每个符号。当这一步完成时程序和全局变量中的每个命令都有一个唯一的运行时地址。

2:重定位部分中的符号引用,在这一步中,链接器将修改对代码和数据中每个符号的引用,以指向正确的运行时地址。

5.6 hello的执行流程

以下函数被依次执行:(函数名后为对应地址)

_start 0x4010f0

_libc_start_main 0x2f12271d

main 0x401125

_printf 0x401040

_sleep 0x401080

_getchar 0x401050

_exit 0x401070

5.7 Hello的动态链接分析

动态共享库是一项解决静态库缺点的现代创新。共享库是一个对象模块,可以在运行或加载时加载到任意内存地址并与程序链接。这个过程称为动态链接。

程序按照模块划分为相对独立的部分,在程序运行时将它们链接在一起形成一个完整的程序,而不是像静态链接那样将所有程序模块链接成一个单独的可执行文件。

.plt:一个数组,每个元素都是一个 16 字节的数据。 PLT[0] 是跳转到动态链接器的特殊条目。可执行程序调用的每个库函数都有自己的 PLT 条目。每个条目负责调用一个特定的函数。

.got:也是数组,每个元素是一个 8 字节地址。当与 PLT 一起使用时,GOT[O] 和 GOT[1] 包含动态链接器在解析函数地址时将使用的信息。 GOT[2] 是 1d-linux.so 模块中动态链接器的入口点。每个剩余的条目对应一个调用函数,其地址需要在运行时解析。每个条目都有一个匹配的 PLT 条目。

动态链接器加载前后hello的重定位不同,加载后进行重定位

5.8 本章小结

本章简要介绍了链接的概念和功能。 linux下的链接命令、hello可执行文件格、式hello虚拟地址空间、hello链接迁移过程分析、hello链接动态过程分析。通过对hello.o可移动目标文件的所有进程进行跟踪分析,展示一个可执行的hello文件的一个比较完整的链接过程。

第6章 hello进程管理

6.1 进程的概念与作用

概念:进程是程序在计算机上的运行活动。系统中资源分配和调度的基本单位。以及操作系统结构的基础在早期的计算机结构中工艺设计进程是程序的基本执行实体。在面向线程设计的当代计算机体系结构中。进程是线程的存储库。程序是对指令、数据和组织的描述,而进程是程序的组成部分。

功能:当像 hello 这样的程序在现代系统上运行时,操作系统可以给进程一种错觉:认为它是系统上运行的唯一程序,并且该程序似乎独占使用处理器、主存储器和 IO 设备, 处理器似乎是一个接一个地不间断地执行程序中的指令,即程序的代码和数据是系统内存中唯一的对象。

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

作用:shell-bash给用户提供一个界面来访问操作系统内核的服务。

处理流程:

1:从终端获取输入命令。

2:将输入字符串转化为参数数组。

3:对于内置命令,执行它。

4:否则尝试调用相应的外部程序。

5:接受通过键盘特殊按键组合输入的信号,并响应这些信号。

6.3 Hello的fork进程创建过程

在 Linux 系统中,用户可以通过 ./ 命令执行一个可执行的目标文件。 ./hello时,shell首先fork()创建一个子进程。(fork() 函数返回 int 类型,在子进程fork中返回0,在父进程fork中返回子进程的Pid) 新创建的进程与父进程几乎相同(子进程获得父进程VM的相同拷贝)

6.4 Hello的execve过程

创建shell子进程后子进程调用 exceve 函数来加载和运行新程序。这就是当前子进程上下文中的 hello 程序。需要执行以下步骤:

1删除已有的用户空间。删除上一步的用户部分中的现有结构。

2生成新的代码、数据、堆和栈段。整个空间的结构是私有的。虚拟地址和数据空间代码空间映射到 hello 文件的 .txt 和 .data 区域。.bss 初始化为0。匿名文件映射以及 hello 文件中包含的文件的大小堆栈和堆空间也请求默认长度为零的二进制密码。

3共享空间映射 如果一个Hello 程序与libc.so 标准C 库等共享对象相关联,则这些对象与程序是动态关联的。然后将其映射到用户虚拟地址空间中的共享空间。

4 设置程序计数器(PC) exceve 做的最后一件事就是将当前进程上下文中的PC设置为指向代码区域的开头。

6.5 Hello的进程执行

1逻辑控制流和时间片:

这个过程的操作本质上是CPU不断地从程序计数器PC指示的地址中取出指令并执行它们。值的序列称为控制的逻辑流。操作系统会调度进程的运行,执行进程A->上下文切换->执行进程B->上下文切换->执行进程A->...等等。在进程执行期间的某个时刻,内核可以决定抢占当前进程并重新启动先前被抢占的进程。这个决定称为调度,由内核中称为调度程序的代码处理。当内核选择一个新进程来运行时,我们说内核调度该进程。内核调度一个新进程运行后,它会抢占当前进程并使用上下文切换机制将控制权转移给新进程。当一个程序被调用并开始被另一个进程中断时,其间的时间就是运行时片。

2用户模式和内核模式:

Hello通常在用户模式进行,访问权限受限,个别函数调用使其进入内核模式,有完全的权限

3 上下文切换

如果系统调用在等待事件时被阻塞,内核可以让当前进程休眠并切换到另一个进程。上下文是内核重新启动抢占进程所需的状态,是一种比较高级的异常控制。流动。

4 调度

在调度进程的过程中,操作系统主要做了两件事:加载保存的寄存器和切换虚拟地址空间。

6.6 hello的异常与信号处理

正常运行:

Ctrl-Z暂停:

进程仍存在,ps能看到进程

Fg恢复前台运行并结束

Ctrl-C:

中止,不再存在hello

“脸滚键盘”:

多余输入被忽略,同时每次输出会导致输入跟着换行

Ctrl-Z后续:

Jobs列出了被暂停的hello

6.7本章小结

本章简要介绍了进程的概念和作用。 Shell函数和进程等,并详细描述了Hello进程的创建、加载、执行、结束的整个过程,并介绍了一些实现细节和进程实现过程中的Hello进程。分析流程实施过程中的异常情况和安排。

由本章可见,进程垄断整个CPU和内存空间只是一种假象。实际上多个进程通过操作系统的进程调度机制获得这一假象。

第7章 hello的存储管理

7.1 hello的存储器地址空间

物理地址:加载到内存地址寄存器中的地址,内存单元的真实地址。 CPU通过地址总线的寻址找到真正物理内存对应的地址。 在前端总线上传输的内存地址都是物理内存地。

线性地址:线性地址是逻辑地址到物理地址转换之间的中间层。 在一个分段单元中,逻辑地址就是段中的偏移地址,再加上基地址就是线性地址。

逻辑地址:指程序生成的与段相关的偏移地址部分,以[段标识符:段内偏移]的形式表示,由段标识符加上相对地址在段内的偏移组成 段。

虚拟地址:程序访问内存所使用的地址。

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

在Intel平台下,逻辑地址格式为段标识符:段内偏移。段标识符由一个称为段选择器的 16 位字段组成,前 13 位是索引号,后 3 位包含一些硬件细节。分段机制将逻辑地址转换为线性地址的步骤如下:

通过使用段选择器中的偏移值,在 GDT 或 LDT 表中找到相关的段描述符。

使用段选择器检查段的访问权限和范围,以确保段可以到达。

将段描述符中获得的段的基地址添加到偏移量。最后创建一个线性地址

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

实际内存被分为页,VM中也分为一样大小的页,每个进程有一个页表,保存VM的页到实际内存的页的映射状态

分为 未分配,未缓存,缓存三种状态

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

从VA到PA的转化需要访问页表,但直接向内存访问页表可能十分缓慢,即使页表在或者部分在缓存中也是,因此在CPU中设置了专门的缓存用于保存一部分页表

四级页表:

直接保存页表占用的空间会较大,而页表中大部分通常是空白的,因此使用四级页表:一种类似指针实现的线段树的结构,来保存页表,特点是连续空白的页表段实际上只会占用极少的空间来存储

实际操作:CPU首先向TLB查找页表条目,查找不到则在四级页表中查找对应条目并更新缓存

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

获取物理地址后,逐级访问Cache并在该级cache中查找是否存在对应数据,查找不到则向下一级继续直到找到缓存或者达到内存,然后逐渐向上,在把数据传递给CPU的同时更新缓存内容,找空白空间或者移除一块以保存刚访问的数据

7.6 hello进程fork时的内存映射

fork后的子进程的VM为父进程VM的副本,同时使用copy-on-write机制,使得两个进程看起来好像独占内存,互不干扰

7.7 hello进程execve时的内存映射

exec以指定程序的内容来更新进程VM,因此导致虚拟内存中一些页被删除,一些页被分配

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

当要访问的页不在内存中时(uncached),需要向硬盘寻找对应的页,由于耗时极长,内核会中断当前程序切换到其他程序(以便充分利用CPU),直到从硬盘加载完成对应的页到内存,然后内核会恢复当前进程并将PC设置到原位置,重新访问该页,此时页已在内存中可以正常向下执行

7.9动态存储分配管理

malloc free提供动态地申请和释放空间的功能,申请时从内存中找足够长的连续未分配段,占用并返回,释放时将这些段标记为空闲

为了高效完成目标,有多种实现方式

一种方式是将连续的长段视为一个整体,并在开头结尾做标记,利用标记寻找合适的段;在“分配时是否将剩余部分设为一个新段”,“free后是否、何时合并相连的空闲段”等问题上的策略有多种选择,效率上也有相应的区别

另一种方式是将内存分为多种固定大小的段,确保段的长度始终是某一预设值,有多种策略进行段的分裂和合并

7.10本章小结

本章介绍了存储器地址空间、段式管理、页式管理,VA 到 PA 的变换、物理内存访问, hello 进程fork时和execve 时的内存映射、缺页故障与缺页中断处理、包括隐式空闲链表和显式空闲链表的动态存储分配管理。

第8章 hello的IO管理

8.1 Linux的IO设备管理方法

网络、磁盘、终端等所有 I/O 设备都模拟为文件。 并且所有输入和输出都被读取并写入它们各自的文件。 设备和文件的良好配对。 这允许 Linux 内核引入一个简单的低级 API,称为 Unix I/O。

8.2 简述Unix IO接口及其函数

基本函数是open()close()read()write()实现字面意义上的功能,其中read write需要指定长度,直接使用可能不便、低效

8.3 printf的实现分析

Printf:

int printf(const char *fmt, ...)

{

int i;

char buf[256];

va_list arg = (va_list)((char*)(&fmt) + 4);

i = vsprintf (buf, fmt, arg);

write (buf, i);

return i;

}

调用vsprintf以实现格式化字符串,然后用write函数输出,write函数调用系统函数完成输出过程

Vsprintf:

int vsprintf(char *buf,const char *fmt,va_list args)

{

char *p;

char tmp[256];

va_listp_next_arg = args;

for (p = buf; *fmt; fmt++)

{

if(*fmt != '%')

{

*p++ = *fmt;

continue;

}

fmt++;

switch(*fmt)

{

case 'x':

itoa(tmp, *((int *)p_next_arg));

strcpy(p, tmp);

p_next_arg += 4;

p += strlen(tmp);

break;

case 's':

break;

default:

break;

}

return (p - buf);

}

}

(实现格式化功能)

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;

}

首先这里设置了缓冲区,以免每次都要调用系统函数read(这样较慢)

n>=0的判断实现了将read的EOF传递的效果

8.5本章小结

本章简要介绍Linux系统的IO管理,简要介绍IO接口和UNIX功能,分析printf和getchar的使用,通过这些分析展示程序如何获取用户输入并在屏幕上打印数据。 . 展示了 IO 管理的强大功能

结论

1.编写:用C语言编写hello.c源代码。

2.预处理:预处理器对hello.c进行处理,将所有调用的外部库进行扩展合并,生成一个hello.i文件。

3. 编译:编译器将 hello.i 转换为汇编语言文件。

4.汇编:汇编器将hello.s文件转换为二进制格式的hello.o可移动目标文件。

5. 链接:链接器将 hello.o 与库链接并移动以创建可执行的 hello。

6、创建子进程:用户在shell中输入命令运行Hello后,shell通过fork创建进程。

7.加载:Shell调用execve,在上下文中加载hello可执行文件,并启动hello。

8. 执行:hello程序正在运行,在此过程中可能会产生异常,需要通过信号处理器调用来处理用户键盘输入ctrl+z、ctrl+c等信号。在运行程序的过程中,Hello 还使用了几种复杂的内存访问机制。

9. 终止:Hello 程序在收到信号后停止或停止。主要流程已经结束。并且 hello 子进程被回收。内核会删除内存中为hello生成的相关数据。

感悟:
操作系统通过多个层面的配合(进程、VM等)使得程序可以认为自己独立地占用整个机器,这是复杂但十分有效、十分重要的机制

附件

hello.c:C语言源程序

hello.i:hello.c预处理的文本文件

hello.s:hello.i编译后的汇编文件

hello.o:hello.s汇编后的可重定位(relocatable)文件

hello.o.elf.txt:hello.o经过readelf得到的文本文件

hello:可执行文件

hello.elf.txt:hello经readelf得到的文本文件

hello.o.s:hello.o经objdump得到的汇编代码

hello.oo:hello.oo经objdump得到的汇编代码

参考文献

[1]  Computer Systems A Programmer's Perspective

[2]  https://www.tutorialspoint.com/unix_commands/readelf.htm

[3]  https://www.tutorialspoint.com/unix_commands/objdump.htm

哈尔滨工业大学-计算机系统-2022春-大作业相关推荐

  1. 哈尔滨工业大学计算机系统大作业2022春

    计算机系统 大作业 题     目 程序人生-Hello's P2P 专       业 计算机 学   号 120L02**** 班   级 2003005 学       生 无敌飞龙 指 导 教 ...

  2. 哈尔滨工业大学 计算机系统 大作业 22春

    计算机系统大作业 计算机科学与技术学院 2022年5月 摘 要 摘要是论文内容的高度概括,应具有独立性和自含性,即不阅读论文的全文,就能获得必要的信息.摘要应包括本论文的目的.主要内容.方法.成果及其 ...

  3. 2023春 哈尔滨工业大学计算机系统大作业

    计算机系统 大作业 题     目 程序人生-Hello's P2P 专       业 物联网工程 学    号 2021111491 班    级 2137301 学       生 业知翰 指 ...

  4. 哈尔滨工业大学 计算机系统大作业

    计算机系统 大作业 题     目 程序人生-Hello's P2P 专       业 计算机类 学   号 120L022010 班   级 2003007 学       生 窦馨宇 指 导 教 ...

  5. 哈尔滨工业大学计算机系统大作业--程序人生

    计算机系统   大作业 题     目  程序人生-Hello's P2P      专       业   计算机科学与技术        学    号        2021110xxx      ...

  6. [ HIT - CSAPP ] 哈尔滨工业大学 - 计算机系统 - 期末大作业“Hello‘s P2P’”

    计算机系统 大作业 题     目 程序人生-Hello's P2P 专       业 计算学部 学    号 120L020731 班    级 2003005 学       生 吴少杰 指 导 ...

  7. 哈尔滨工业大学计算机系统大作业

    计算机科学与技术学院 2021年5月 摘  要 本篇论文分析了程序hello的p2p,020过程,根据书籍<深入理解计算机系统>,对从hello程序的编译,到hello程序的运行的整体过程 ...

  8. 哈尔滨工业大学计算机系统大作业——程序人生-Hello’s P2P

    目录 摘要 第1章 概述 1.1 Hello简介 1.1.1 P2P:From Program to Process 1.1.2 020:From Zero-0 to Zero-0 1.2 环境与工具 ...

  9. 程序人生-Hello’s P2P——哈尔滨工业大学计算机系统大作业

    摘  要 在这篇文章中,我们主要探究hello程序从几行源代码到真正变成一个程序,实现自身功能,最后被回收的过程.在这个过程中,我们按照课程知识体系的流程,一步步对hello进行分析阐述,分析程序在计 ...

最新文章

  1. Python 21 Flask(二)上下文管理详解
  2. 盘点 | 近期活动信息都在这里啦~
  3. Jmeter连接mysql(一)
  4. excel 公式 单引号 concat_从Excel的数据类型说Python
  5. TCP/IP网络协议栈:IP协议
  6. Graham-Scan小总结——toj2317 Wall
  7. MTK FM收音机修改门限减少杂台
  8. knockoutjs 读源码
  9. 计算机word题目设置标题,word文档标题怎么设置?word设置标题样式的方法
  10. ECMAScript基础
  11. c语言:数据保存的方法实现简易贪吃蛇
  12. 计算机电路英文专业翻释术语,电子专业词汇翻译中英文对照(新手必备知识)
  13. 分享 2022 年最受欢迎的黑科技工具(二)
  14. 自动化重复文件清理 Bash 脚本
  15. html5怎么让图片垂直居中显示,css中如何实现图片垂直居中显示?
  16. 献给那些有梦想的程序员'
  17. 中国流动人口数据(cmds)
  18. 编程图记(2): 学用PHP框架Laravel
  19. 基于.net6.0在wpf桌面应用中发布webApi服务示例
  20. SMBJ5.0A-TR介绍

热门文章

  1. 平安养老险党委书记、董事长甘为民:做实、做多、做大养老三支柱
  2. SqlSugar 集成
  3. 正睿OI补题(递归与递推,前缀和与差分)
  4. iOS应用架构谈 view层的组织和调用方案
  5. fedora 18 19 20 21 22 23 怎么安装中文语言包
  6. Tesla+Quadro大一统:NVIDIA发布Maximus
  7. 婚礼拍得像MV一样,好感动!(男的看了都想结婚了)
  8. 【Visual Leak Detector】简介
  9. 坐标轴刻度取值算法-基于魔数数组-源于echarts的y轴刻度计算需求
  10. 图论——二分图——最小点覆盖