操作系统,loader以及应用服务器 应用服务器WindowsUnixOS数据结构
程序员文章站
2022-07-11 17:38:05
...
这是该系列的第二部分。
上次说道,OS主要分成计算的管理,存储的管理和IO的管理,其中,计算的管理从OS的角度来看是最重要最根本的。
注:我们暂时不考虑并发。
我们现在要从一个动态的角度看问题了。基于程序存储+图灵机这个基本思想,我们构建了现在形形色色的计算机系统。既然程序是被存储的,那么它一定被放在存储系统里面,而对于运算,实际上是一系列的指令来控制计算的进行。这里面就涉及到存放在存储系统里的静态的程序怎么幻化成可以操纵计算的动态的操作者。
这个过程叫做loader。loader就是把程序从静态的存储状态转换为动态的进程状态,然后这个动态的程序就可以控制计算过程了。
说到这儿,不得不先明确几个基本概念了。
进程:运行着的程序。
程序:有运行潜力的,包含控制运算的指令集合的文件。
文件:存储系统管理的基本单位,每种文件都可以有自己特定的内部结构。但是对于操作系统来说,这些结构大都是不可见的。操作系统一般把文件看成简单的字节序列。
每一个文件都需要有一个或者多个自己的解析器,这些解析器可以解释文件形成特定的意义。
loader:装载器,程序文件的解析器,它负责解释程序文件,形成进程。请注意,它本身也是一个运行着的程序,也就是进程。这里似乎是一个无法解开的死结,其实不然,想想计算机的启动过程就明白了。
装载器的职责包括解释可执行文件,为它们准备好执行环境,也就是执行开始或者过程中可能会需要的各种资源,所依赖的各种库,以及需要的场地。狭义一点,整个操作系统都可以看成是为各种应用提供运行环境的一个系统。看到这儿想起什么了?——应用服务器。对,就是应用服务器。不过应用服务器一般还提供负载均衡、应用分区、应用池及重新回收和利用等等高端的特性。不过,Windows2003自己也提供了这些特性,所以难怪Windows会号称自己就是应用服务器了。
先说一些外围技术,前面提到的可执行文件,其实就是程序文件,它们会被装载器解释,现在的问题是:我随便给一个文件,让装载器解释执行,会有什么问题?答案,没有什么问题。原因:所有的文件的内容都是数据。可是这……,这不可能,也不应该啊。对,是不应该。所以我们需要一些约定。比如:Windows的约定是文件扩展名。文件扩展名是文件名最后一个点以后的部分。对于某些特定文件扩展名(确切地说是:com exe cmd bat msc scr cpl等等),Windows的装载器就会认为它是可执行的,进而试图执行之。
而UNIX类的操作系统,不是通过文件名约定的,而是通过文件系统中的文件属性来约定的,那种属性中包括x(可执行)的文件就是可执行文件。
其实,上面的描述还隐藏了一些细节,我通过原生的和次生的这两个概念来把隐藏的揭露出来:)
不过,我首先还要描述一个叫做魔术字的概念。
魔术字就是某个字,它一般是2的某个幂(这个幂可能是0 1 2 3,再多了就比较少见了)长,当然,也不一定。它会被放在某些需要做标记的文件开头,一个特定的魔术字就代表一个特定的文件类型。这个约定跟前面两种形式的约定相比,有很多比较明显的优势和劣势,一般都会双管齐下,互为备份的。
现在开始我们原生和次生:)。
所谓原生,就是由装载器直接装载运行的那种可执行文件。所谓次生,是由装载器装载入另一个解释器,由这个解释器去装载运行这个可执行文件的。呵呵,差别似乎不是很大,但是由于增加了一个间接层,我们有了很多腾挪的余地。比如:Windows平台的JS文件,UNIX平台的perl文件,再一次的,UNIX 在这些文件上提供了方便于Windows的特性,它们(脚本文件们)一般都有一个叫做dingbang(或许我写错了……)的首行,用来指定自己的解释器。
现在我得解释一下在装载器看来可执行文件的格式(我现在只关注原生的可执行文件)。
对于任何文件,如果相对复杂,一般都会有一个头部,记录相关的元数据。可执行文件也不例外。
对于可执行文件,历史上有过很多格式,其中最简单的那种甚至没有头部,就直接是指令集合。最经典的例子就是DOS下的com文件。当然还有很多别的格式, a.out格式是其中非常出名的一种格式,甚至前不久还在用。但若论影响力和持久性,最出名的可执行文件格式非COFF和ELF莫属。COFF和ELF似乎都是贝尔实验室整出来的格式(对于ELF我有点拿不准),ELF是COFF的继任者。Windows上的PE格式就是一种COFF格式。
……,时间有限,先到此为止!
上次说道,OS主要分成计算的管理,存储的管理和IO的管理,其中,计算的管理从OS的角度来看是最重要最根本的。
注:我们暂时不考虑并发。
我们现在要从一个动态的角度看问题了。基于程序存储+图灵机这个基本思想,我们构建了现在形形色色的计算机系统。既然程序是被存储的,那么它一定被放在存储系统里面,而对于运算,实际上是一系列的指令来控制计算的进行。这里面就涉及到存放在存储系统里的静态的程序怎么幻化成可以操纵计算的动态的操作者。
这个过程叫做loader。loader就是把程序从静态的存储状态转换为动态的进程状态,然后这个动态的程序就可以控制计算过程了。
说到这儿,不得不先明确几个基本概念了。
进程:运行着的程序。
程序:有运行潜力的,包含控制运算的指令集合的文件。
文件:存储系统管理的基本单位,每种文件都可以有自己特定的内部结构。但是对于操作系统来说,这些结构大都是不可见的。操作系统一般把文件看成简单的字节序列。
每一个文件都需要有一个或者多个自己的解析器,这些解析器可以解释文件形成特定的意义。
loader:装载器,程序文件的解析器,它负责解释程序文件,形成进程。请注意,它本身也是一个运行着的程序,也就是进程。这里似乎是一个无法解开的死结,其实不然,想想计算机的启动过程就明白了。
装载器的职责包括解释可执行文件,为它们准备好执行环境,也就是执行开始或者过程中可能会需要的各种资源,所依赖的各种库,以及需要的场地。狭义一点,整个操作系统都可以看成是为各种应用提供运行环境的一个系统。看到这儿想起什么了?——应用服务器。对,就是应用服务器。不过应用服务器一般还提供负载均衡、应用分区、应用池及重新回收和利用等等高端的特性。不过,Windows2003自己也提供了这些特性,所以难怪Windows会号称自己就是应用服务器了。
先说一些外围技术,前面提到的可执行文件,其实就是程序文件,它们会被装载器解释,现在的问题是:我随便给一个文件,让装载器解释执行,会有什么问题?答案,没有什么问题。原因:所有的文件的内容都是数据。可是这……,这不可能,也不应该啊。对,是不应该。所以我们需要一些约定。比如:Windows的约定是文件扩展名。文件扩展名是文件名最后一个点以后的部分。对于某些特定文件扩展名(确切地说是:com exe cmd bat msc scr cpl等等),Windows的装载器就会认为它是可执行的,进而试图执行之。
而UNIX类的操作系统,不是通过文件名约定的,而是通过文件系统中的文件属性来约定的,那种属性中包括x(可执行)的文件就是可执行文件。
其实,上面的描述还隐藏了一些细节,我通过原生的和次生的这两个概念来把隐藏的揭露出来:)
不过,我首先还要描述一个叫做魔术字的概念。
魔术字就是某个字,它一般是2的某个幂(这个幂可能是0 1 2 3,再多了就比较少见了)长,当然,也不一定。它会被放在某些需要做标记的文件开头,一个特定的魔术字就代表一个特定的文件类型。这个约定跟前面两种形式的约定相比,有很多比较明显的优势和劣势,一般都会双管齐下,互为备份的。
现在开始我们原生和次生:)。
所谓原生,就是由装载器直接装载运行的那种可执行文件。所谓次生,是由装载器装载入另一个解释器,由这个解释器去装载运行这个可执行文件的。呵呵,差别似乎不是很大,但是由于增加了一个间接层,我们有了很多腾挪的余地。比如:Windows平台的JS文件,UNIX平台的perl文件,再一次的,UNIX 在这些文件上提供了方便于Windows的特性,它们(脚本文件们)一般都有一个叫做dingbang(或许我写错了……)的首行,用来指定自己的解释器。
现在我得解释一下在装载器看来可执行文件的格式(我现在只关注原生的可执行文件)。
对于任何文件,如果相对复杂,一般都会有一个头部,记录相关的元数据。可执行文件也不例外。
对于可执行文件,历史上有过很多格式,其中最简单的那种甚至没有头部,就直接是指令集合。最经典的例子就是DOS下的com文件。当然还有很多别的格式, a.out格式是其中非常出名的一种格式,甚至前不久还在用。但若论影响力和持久性,最出名的可执行文件格式非COFF和ELF莫属。COFF和ELF似乎都是贝尔实验室整出来的格式(对于ELF我有点拿不准),ELF是COFF的继任者。Windows上的PE格式就是一种COFF格式。
……,时间有限,先到此为止!
上一篇: url的组成
下一篇: 浅谈 HTTP 协议