基于《程序员的自我修养》《深入理解计算机系统》《计算机系统的构造和解释》《游戏脚本高级编程》四本书的读后感。
可执行文件的装载与进程
Linux内核装载ELF过程简介
运行库
程序的入口函数
- 操作系统在创建进程后,把控制权交到了程序的入口,这个入口往往是运行库中的某个入口函数。
- 入口函数对运行库和程序运行环境进行初始化,包括堆、I/O、线程、全局变量构造,等等。
- 入口函数初始化完成后,调用main函数,正式开始执行程序主体部分。
- main函数执行完毕后,返回到入口函数,入口函数进行清理工作,包括全局变量析构、堆销毁、关闭I/O等,然后进行系统调用结束进程。
glibc和MSVC的入口函数实现
glibc的程序入口函数为_start,_start由汇编实现,并且和平台相关。在调用_start函数前,装载器会把用户的参数和环境变量压入栈中。_start函数最终调用__lib_start_main函数,实际执行代码的函数是__lib_start_main。
__lib_start_main函数接收7个参数:
- main函数指针
- argc
- argv
- init
- fini
- tfld_fini
运行库与I/O
C语言文件操作是通过一个FILE结构的指针来进行的,fopen函数返回一个FILE结构的指针。在操作系统层面文件操作分别在:Linux中,叫做文件描述符(File Descriptor);Windows里,叫做句柄(Handle)。用户通过某个函数打开文件以获得句柄,之后用户操作文件都通过该句柄。文件的句柄总是和内核的文件对象相关联。内核通过句柄来计算出内核里文件对象的地址。
在内核中,每一个进程都有一个私有的“打开文件表”,这个表是一个指针数组,每个元素指向一个内核的打开文件对象。而fd,就是这个表的下标。用户打开一个文件,内核会生成一个打开文件对象,添加到数组中,然后返回下标fd。由于这个表数组处于内核,并且用户无法访问到,因此即使用户拥有fd,也无法得到打开文件对象的地址,只能够通过系统提供的函数来操作。
在C语言中,操作文件是通过FILE结构,FILE结构和fd有一对一关系,每个FILE结构都记录自己唯一对应的fd。
MSCV CRT的入口函数初始化
系统堆初始化 MSVC的入口函数初始化主要包含两个部分,堆初始化和I/O初始化。堆初始化由_heap_init函数完成,_heap_init调用HeapCreate API创建一个系统堆。MSVC的malloc函数就是调用HeapAlloc API,将堆管理交给操作系统。 I/O初始化:建立打开文件表;如果能够继承自父进程,那么从父进程获取继承的句柄;初始化标准输入输出。
C/C++运行库
Runtime Libary,C运行库(CRT)。大致包含如下功能:
- 启动与退出
- 标准函数
- I/O
- 堆
- 语言实现
- 调试
运行库是平台相关的,与操作系统紧密结合。C语言的运行库是C语言的程序和不同操作系统平台之间的抽象层,它将不同操作系统API抽象成相同的库函数。但是各操作系统的限制都不相同,所以有很多范畴(比如用户的权限控制、操作系统线程创建等)都不属于标准的C语言运行库。于是我们不得不绕过C语言运行库直接调用操作系统API或使用其他库。Linux C语言运行库为glibc(GNU C Library),Windows为MSVCRT(Microsoft Visual C Run-time)。但是比如C语言运行库为了保证多平台之间能够相互通过,于是只能取各个平台之间功能的交集。
系统调用与API
系统调用是通过中断来实现的,Linux使用0x80号中断作为系统调用的入口,Windows采用0x2E号中断作为系统调用入口。
Windows API是以DLL导出函数的形式暴露给应用程序开发者的。微软把这些Windows API DLL导出函数的声明的头文件、导出库、相关文件和工具一起打包称为SDK(Software Development Kit)。
XtremeScript
《游戏脚本高级编程》读书思考
汇编器
《第4篇 设计和实现一种底层语言》介绍汇编器的实现,实现了一个完整的汇编器。
汇编器是如何运作的
汇编器的功能: (1)遍历源码处理指示符,包括行标签索引和函数入口点的处理。 (2)再次遍历源码把每条指令汇编成相等的机器码,同时还要解析跳转行标签和函数调用。 (3)使用已构造好的XVM可以识别的格式把已经完成的数据输出到一个二进制文件中。
汇编过程: (1)根据指令查找表把每个指令助记符转为相应的操作码。 (2)根据所有变量和数组引用所在的作用域,把它们转变成相关的堆栈索引。 (3)注意指令流中的行标签索引,把指令后面的引用转换成索引。 (4)丢弃所有无关内容比如空白符、逗号等。把所有东西转为ASCII码相对应的二进制格式。 (5)采用XML格式,将内容输出到二进制文件,作为可执行文件,
虚拟机
《第5篇 设计和实现虚拟机》介绍虚拟机的实现,实现了一个完整的虚拟机。
编译器
《第6篇 编译高级代码》介绍编译器的实现,实现了一个完整的编译器。