内容简介 · · · · · ·
这本书主要介绍系统软件的运行机制和原理,涉及在Windows和Linux两个系统平台上,一个应用程序在编译、链接和运行时刻所发生的各种事项,包括:代码指令是如何保存的,库文件如何与应用程序代码静态链接,应用程序如何被装载到内存中并开始运行,动态链接如何实现,C/C++运行库的工作原理,以及操作系统提供的系统服务是如何被调用的。每个技术专题都配备了大量图、表和代码实例,力求将复杂的机制以简洁的形式表达出来。本书最后还提供了一个小巧且跨平台的C/C++运行库MiniCRT,综合展示了与运行库相关的各种技术。
对装载、链接和库进行了深入浅出的剖析,并且辅以大量的例子和图表,可以作为计算机软件专业和其他相关专业大学本科高年级学生深入学习系统软件的参考书。同时,还可作为各行业从事软件开发的工程师、研究人员以及其他对系统软件实现机制和技术感兴趣者的自学教材。
对装载、链接和库进行了深入浅出的剖析,并且辅以大量的例子和图表,可以作为计算机软件专业和其他相关专业大学本科高年级学生深入学习系统软件的参考书。同时,还可作为各行业从事软件开发的工程师、研究人员以及其他对系统软件实现机制和技术感兴趣者的自学教材。
豆瓣成员常用的标签(共219个) · · · · · ·
喜欢读"程序员的自我修养"的人也喜欢 · · · · · ·
按有用程度 按页码先后 最新笔记
-
第1页
vivi (执子之手,将子拖走)
一、程序的编译过程,目标文件里究竟是什么 从源程序到目标文件的生成过程 最简单的编译命令是gcc helloworld.c,它包含了以下几个步骤: 预处理、编译、汇编、链接,下面分别简介。 预处理:处理#define宏定义、#if #ifdef等条件编译指令、#include预编译指令,删除注释,添加行号和文件名标识,保留所有的#pargma编译器指令,经过预编译后的文件为.i文件。预编译命令为:gcc -E hello.c -o hello.i或者cpp hello.c > ... (更多)一、程序的编译过程,目标文件里究竟是什么从源程序到目标文件的生成过程最简单的编译命令是gcc helloworld.c,它包含了以下几个步骤:预处理、编译、汇编、链接,下面分别简介。预处理:处理#define宏定义、#if #ifdef等条件编译指令、#include预编译指令,删除注释,添加行号和文件名标识,保留所有的#pargma编译器指令,经过预编译后的文件为.i文件。预编译命令为:gcc -E hello.c -o hello.i或者cpp hello.c > hello.i编译:把预处理完得文件进行一系列的词法分析、语法分析、语意分析及优化后产生的汇编代码文件。编译命令为gcc -S hello.i -o hello.s。现在版本的gcc把预编译和编译两个步骤合并成一个步骤,使用ccl程序来完成,命令为ccl hello.c。也可以使用gcc -S hello.c -o hello.s直接从.c文件生成.s汇编文件。汇编:将汇编代码转变成机器可以执行的指令,每一条汇编语句几乎都对应一条机器指令。命令为:as hello.s -o hello.o或者gcc -c hello.s -o hello.o或者我们最熟悉的gcc -c hello.c -o hello.o链接:当我们的程序模块调用a另一个模块中b的函数(foo())或变量时,在编译的阶段编译器并不知道函数foo的地址,所以暂时把调用foo的指令的目标地址搁置,等待最后链接的时候由连接器去将这些指令的目标地址修正。把目标文件和库一起链接成可执行文件。最常见的库时运行时库。目标文件中的格式目标文件就是源代码编译后但未进行链接的那些中间文件,它和可执行文件的内容和结构其实很相似,所以一般和可执行文件采用同一种格式存储,那就是ELF格式。与ELF格式相对应的是Windows平台下的PE格式,它们都是COFF格式的变种。不光是可执行文件和目标文件按照ELF格式存储,动态链接库(.so)和静态链接库(.a)都按照ELF格式存储。ELF格式的文件可分为以下4类:1 可重定位文件(Relocatable File):这类文件包含了代码和数据,可以被用来链接成可执行文件或共享目标文件,静态链接库也可以归为这一类,代表是Linux的.o文件2 可执行文件(Executable File):这类文件包含了可以直接执行的程序,它的代表就是ELF可执行文件,它们一般都没有扩展名,如/bin/bash文件3 共享目标文件(Shared Object File):这种文件包含了代码和数据,可以在以下两种情况下使用。一种是链接器可以使用这种文件跟其他的可重定位文件和共享目标文件链接,产生新的目标文件。第二种是动态链接器可以将这几个共享目标文件与可执行文件结合,作为进程影响的一部分来运行。4 核心转储文件(Core Dump File):当进程意外终止时,系统可以将该进程的地址空间的内容以终止时的一些其他信息转储带核心转储文件。上面几种文件在file命令下会显示出相应的类型。目标文件里有什么:ELF文件最重要的结构是ELF文件头(ELF Header):ELF文件头里定义了ELF魔数、文件机器字节长度、数据存储方式、版本、运行平台、ABI版本、ELF重定位类型、硬件平台、硬件平台版本、入口地址、程序头入口和长度、段表的位置和长度及段得数量等。三个最重要的段:代码段(.text)、数据段(.data)和只读数据段(.rodata)、BSS段(.bss)可以用objdump -s -x -d hello.o来分析各个段得内容,-d表示反汇编,-s表示把各段内容用16进制打印,-x表示详细数据。 顾名思义,.text段主要存放可执行的代码数据;.data段保存的是已经初始化了的全局变量和静态变量;.rodata段保存只读数据,一般是程序里的只读变量(如const修饰的变量)和字符串常量;bss保存未初始化的全局变量和静态变量。除此之外,还有一些常见的段,如.comment段存放编译器版本信息,比如字符串“GCC:(GNU)4.2.0”.dubug段存放调试信息.dynamic存放动态链接信息.hash段存放符号哈希表.line段存放调试时的行号表.note段存放额外的编译器信息.strtab段存放字符串表,用于存储ELF文件中用到的各种字符串,比如符号的名字.shstrtab段存放段表中用到的字符串,最常见的就是段名.symtab段是符号表,通过符号表就能知道这个符号在哪个段,以及在这个段的具体位置,还有这个符号在字符串表中的位置Section Table(段表)也是其中一个段,它保存了各个段的信息,如段名、段的长度、在文件中的偏移、读写权限及段的其他属性.rel.text段是一个重定位表,正如前面所说的,链接器在处理目标文件时,需要对目标文件的某些部位进行重定位,即代码段和数据段中那些对绝对地址的引用的位置,这些重定位的信息都记录在ELF文件的重定位表里通过ELF文件头的信息可以找到段表的位置,从而找到各个段得位置和信息。可以用readelf -S hello.o命令详细查看ELF文件中各段的信息。二、可执行文件的装载程序执行时所需要的指令和数据必须都在内存中才能正常运行,最简单的办法就是将程序运行时所需要的指令和数据全部都装入内存,这样程序就能顺利执行,这就是最简单的静态装入的方法。但是程序所需要的内存数量可能大于物理内存,静态装入就不太现实。 后来研究发现,程序运行时具有局部性原理,所以我们可以将程序最常用的部分驻留在内存中,而将一些不太常用的数据存放在磁盘上,这就是动态装载的原理。 覆盖装入和页映射是两种典型的动态装入方法。覆盖装入就是如果两个模块不会同时运行,则可以使这两个模块共用一块内存,需要哪个模块的时候就装入。现在基本已经淘汰了。 页映射是虚拟存储机制的一部分,它随着虚拟存储的发明而诞生。在页映射机制中,程序装载和操作的单位都是页。最常见的Inter IA32处理器一般都使用4KB大小的页。 假设程序所有的指令和数据总和为32kB,那么程序总共分为8页,将其编号为P0-O7,并假设物理内存只有16kB,编号为F0-F3。如果程序刚开始执行时的入口地址为P0,这时装载管理器发现程序的P0不在内存中,于是将F0分配给P0,并将P0的内容装入F0;运行一段时间后,程序需要用到P5,于是装载管理器将P5装入F1,就这样,当程序用到P3和P6时,它们分别装入到了F2和F3。 很明显,如果这时程序只需要P0,P3,P5和P6这4个页,那么程序就能一直运行下去。但是如果这时候需要访问P4,那么装载管理器需要最初选择,它必须放弃目前正在使用的4个物理内存页中的一个来装载P4。至于选择哪个页,可以有多种算法选择,比如FIFO先入先出算法,LRU最近最少使用算法等。 其实,上面所说的装载管理器就是操作系统的存储管理器。从操作系统的角度看可执行文件的装载 从操作系统的角度看,一个进程最关键的特征就是它拥有独立的虚拟地址空间,这使得它有别于其他进程。这在http://blog.csdn.net/vividonly/archive/2011/05/04/6393516.aspx一文中有详细解释。要使一个可执行程序得以执行,首先必须创建一个进程,然后装载相应的可执行文件并且执行。在有虚拟存储的情况下,上述过程最开始只要做三件事: 1 创建一个独立的虚拟地址空间。这时候并不设置虚拟地址页和物理地址页的映射关系,这些映射关系等到后面程序发生页错误的时候再进行设置。当发生页错误时,操作系统将从物理内存中分配一个物理页,然后将该“缺页”从磁盘中读取到内存中再设置缺页的虚拟页与物理页的映射关系。这都是通过CPU的MMU来实现的。 2 读取可执行文件头,并且建立虚拟空间与可执行文件的映射关系。这个映射关系在进程中叫做VMA(虚拟内存区域)。比如对于.text段,在创建进程后,会在进程相应的数据结构中设置一个.text段的VMA,记录了它在虚拟空间的地址以及它在ELF文件中的偏移。当程序执行发生页错误,通过查找VMA结构来定位错误页在可执行文件的位置,把可执行文件的那部分内容装入刚分配的物理内存中,进程从刚才页错误的位置重新开始执行。 3 将CPU的指令寄存器设置为可执行文件的入口地址,启动运行。操作系统通过设置CPU的指令寄存器将控制权转交给进程。这里的入口地址就是ELF文件头中的入口地址。 (收起)2011-05-06 17:24:11 2回应
-
可执行文件的格式
jermaine (开始豆瓣)
.text和.data段分开有若干个好处: 1. 可以对code段写保护。 2. 多个进程可以共享code段。 3. locality .bss段并不需要存储数据,因为在这个段中的变量全部是未初始化的全局变量或者局部静态变量。有时候编译器也会将初始化为0的静态变量放在bss段。 (更多).text和.data段分开有若干个好处:1. 可以对code段写保护。2. 多个进程可以共享code段。3. locality.bss段并不需要存储数据,因为在这个段中的变量全部是未初始化的全局变量或者局部静态变量。有时候编译器也会将初始化为0的静态变量放在bss段。 (收起)2011-12-28 13:50:47 回应
-
第1页
vivi (执子之手,将子拖走)
一、程序的编译过程,目标文件里究竟是什么 从源程序到目标文件的生成过程 最简单的编译命令是gcc helloworld.c,它包含了以下几个步骤: 预处理、编译、汇编、链接,下面分别简介。 预处理:处理#define宏定义、#if #ifdef等条件编译指令、#include预编译指令,删除注释,添加行号和文件名标识,保留所有的#pargma编译器指令,经过预编译后的文件为.i文件。预编译命令为:gcc -E hello.c -o hello.i或者cpp hello.c > ... (更多)一、程序的编译过程,目标文件里究竟是什么从源程序到目标文件的生成过程最简单的编译命令是gcc helloworld.c,它包含了以下几个步骤:预处理、编译、汇编、链接,下面分别简介。预处理:处理#define宏定义、#if #ifdef等条件编译指令、#include预编译指令,删除注释,添加行号和文件名标识,保留所有的#pargma编译器指令,经过预编译后的文件为.i文件。预编译命令为:gcc -E hello.c -o hello.i或者cpp hello.c > hello.i编译:把预处理完得文件进行一系列的词法分析、语法分析、语意分析及优化后产生的汇编代码文件。编译命令为gcc -S hello.i -o hello.s。现在版本的gcc把预编译和编译两个步骤合并成一个步骤,使用ccl程序来完成,命令为ccl hello.c。也可以使用gcc -S hello.c -o hello.s直接从.c文件生成.s汇编文件。汇编:将汇编代码转变成机器可以执行的指令,每一条汇编语句几乎都对应一条机器指令。命令为:as hello.s -o hello.o或者gcc -c hello.s -o hello.o或者我们最熟悉的gcc -c hello.c -o hello.o链接:当我们的程序模块调用a另一个模块中b的函数(foo())或变量时,在编译的阶段编译器并不知道函数foo的地址,所以暂时把调用foo的指令的目标地址搁置,等待最后链接的时候由连接器去将这些指令的目标地址修正。把目标文件和库一起链接成可执行文件。最常见的库时运行时库。目标文件中的格式目标文件就是源代码编译后但未进行链接的那些中间文件,它和可执行文件的内容和结构其实很相似,所以一般和可执行文件采用同一种格式存储,那就是ELF格式。与ELF格式相对应的是Windows平台下的PE格式,它们都是COFF格式的变种。不光是可执行文件和目标文件按照ELF格式存储,动态链接库(.so)和静态链接库(.a)都按照ELF格式存储。ELF格式的文件可分为以下4类:1 可重定位文件(Relocatable File):这类文件包含了代码和数据,可以被用来链接成可执行文件或共享目标文件,静态链接库也可以归为这一类,代表是Linux的.o文件2 可执行文件(Executable File):这类文件包含了可以直接执行的程序,它的代表就是ELF可执行文件,它们一般都没有扩展名,如/bin/bash文件3 共享目标文件(Shared Object File):这种文件包含了代码和数据,可以在以下两种情况下使用。一种是链接器可以使用这种文件跟其他的可重定位文件和共享目标文件链接,产生新的目标文件。第二种是动态链接器可以将这几个共享目标文件与可执行文件结合,作为进程影响的一部分来运行。4 核心转储文件(Core Dump File):当进程意外终止时,系统可以将该进程的地址空间的内容以终止时的一些其他信息转储带核心转储文件。上面几种文件在file命令下会显示出相应的类型。目标文件里有什么:ELF文件最重要的结构是ELF文件头(ELF Header):ELF文件头里定义了ELF魔数、文件机器字节长度、数据存储方式、版本、运行平台、ABI版本、ELF重定位类型、硬件平台、硬件平台版本、入口地址、程序头入口和长度、段表的位置和长度及段得数量等。三个最重要的段:代码段(.text)、数据段(.data)和只读数据段(.rodata)、BSS段(.bss)可以用objdump -s -x -d hello.o来分析各个段得内容,-d表示反汇编,-s表示把各段内容用16进制打印,-x表示详细数据。 顾名思义,.text段主要存放可执行的代码数据;.data段保存的是已经初始化了的全局变量和静态变量;.rodata段保存只读数据,一般是程序里的只读变量(如const修饰的变量)和字符串常量;bss保存未初始化的全局变量和静态变量。除此之外,还有一些常见的段,如.comment段存放编译器版本信息,比如字符串“GCC:(GNU)4.2.0”.dubug段存放调试信息.dynamic存放动态链接信息.hash段存放符号哈希表.line段存放调试时的行号表.note段存放额外的编译器信息.strtab段存放字符串表,用于存储ELF文件中用到的各种字符串,比如符号的名字.shstrtab段存放段表中用到的字符串,最常见的就是段名.symtab段是符号表,通过符号表就能知道这个符号在哪个段,以及在这个段的具体位置,还有这个符号在字符串表中的位置Section Table(段表)也是其中一个段,它保存了各个段的信息,如段名、段的长度、在文件中的偏移、读写权限及段的其他属性.rel.text段是一个重定位表,正如前面所说的,链接器在处理目标文件时,需要对目标文件的某些部位进行重定位,即代码段和数据段中那些对绝对地址的引用的位置,这些重定位的信息都记录在ELF文件的重定位表里通过ELF文件头的信息可以找到段表的位置,从而找到各个段得位置和信息。可以用readelf -S hello.o命令详细查看ELF文件中各段的信息。二、可执行文件的装载程序执行时所需要的指令和数据必须都在内存中才能正常运行,最简单的办法就是将程序运行时所需要的指令和数据全部都装入内存,这样程序就能顺利执行,这就是最简单的静态装入的方法。但是程序所需要的内存数量可能大于物理内存,静态装入就不太现实。 后来研究发现,程序运行时具有局部性原理,所以我们可以将程序最常用的部分驻留在内存中,而将一些不太常用的数据存放在磁盘上,这就是动态装载的原理。 覆盖装入和页映射是两种典型的动态装入方法。覆盖装入就是如果两个模块不会同时运行,则可以使这两个模块共用一块内存,需要哪个模块的时候就装入。现在基本已经淘汰了。 页映射是虚拟存储机制的一部分,它随着虚拟存储的发明而诞生。在页映射机制中,程序装载和操作的单位都是页。最常见的Inter IA32处理器一般都使用4KB大小的页。 假设程序所有的指令和数据总和为32kB,那么程序总共分为8页,将其编号为P0-O7,并假设物理内存只有16kB,编号为F0-F3。如果程序刚开始执行时的入口地址为P0,这时装载管理器发现程序的P0不在内存中,于是将F0分配给P0,并将P0的内容装入F0;运行一段时间后,程序需要用到P5,于是装载管理器将P5装入F1,就这样,当程序用到P3和P6时,它们分别装入到了F2和F3。 很明显,如果这时程序只需要P0,P3,P5和P6这4个页,那么程序就能一直运行下去。但是如果这时候需要访问P4,那么装载管理器需要最初选择,它必须放弃目前正在使用的4个物理内存页中的一个来装载P4。至于选择哪个页,可以有多种算法选择,比如FIFO先入先出算法,LRU最近最少使用算法等。 其实,上面所说的装载管理器就是操作系统的存储管理器。从操作系统的角度看可执行文件的装载 从操作系统的角度看,一个进程最关键的特征就是它拥有独立的虚拟地址空间,这使得它有别于其他进程。这在http://blog.csdn.net/vividonly/archive/2011/05/04/6393516.aspx一文中有详细解释。要使一个可执行程序得以执行,首先必须创建一个进程,然后装载相应的可执行文件并且执行。在有虚拟存储的情况下,上述过程最开始只要做三件事: 1 创建一个独立的虚拟地址空间。这时候并不设置虚拟地址页和物理地址页的映射关系,这些映射关系等到后面程序发生页错误的时候再进行设置。当发生页错误时,操作系统将从物理内存中分配一个物理页,然后将该“缺页”从磁盘中读取到内存中再设置缺页的虚拟页与物理页的映射关系。这都是通过CPU的MMU来实现的。 2 读取可执行文件头,并且建立虚拟空间与可执行文件的映射关系。这个映射关系在进程中叫做VMA(虚拟内存区域)。比如对于.text段,在创建进程后,会在进程相应的数据结构中设置一个.text段的VMA,记录了它在虚拟空间的地址以及它在ELF文件中的偏移。当程序执行发生页错误,通过查找VMA结构来定位错误页在可执行文件的位置,把可执行文件的那部分内容装入刚分配的物理内存中,进程从刚才页错误的位置重新开始执行。 3 将CPU的指令寄存器设置为可执行文件的入口地址,启动运行。操作系统通过设置CPU的指令寄存器将控制权转交给进程。这里的入口地址就是ELF文件头中的入口地址。 (收起)2011-05-06 17:24:11 2回应
-
第1页
邻水风竹 (惯看秋月春风)
计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决,大部分的中间层都是为了封装变化点 linux三个进程创建函数的区别 fork 复制当前进程 exec 使用新的可执行映像覆盖当前可执行映像 clone 创建子进程并从指定位置开始执行 几种锁机制 互斥量:获取互斥量的线程负责释放互斥量,且对系统中任何进程可见 信号量:信号量可由某个线程获取,由另外的线程释放,且对系统中任何进程可见 临界区:可看作只限于.. (更多)计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决,大部分的中间层都是为了封装变化点linux三个进程创建函数的区别fork 复制当前进程exec 使用新的可执行映像覆盖当前可执行映像clone 创建子进程并从指定位置开始执行几种锁机制互斥量:获取互斥量的线程负责释放互斥量,且对系统中任何进程可见信号量:信号量可由某个线程获取,由另外的线程释放,且对系统中任何进程可见临界区:可看作只限于进程内的互斥量volatile 扩展,可防止编译器过度优化后指令执行顺序改变,导致程序异常,volatile 扩展可保证的两件事情1、阻止编译器为了提高速度将一个变量缓存到寄存器而不写回内存2、阻止编译器调整操作volatile变量的指令顺序内存屏障barrier()可阻止CPU将barrier前后的指令执行顺序交换,以解决乱序执行所带来的问题readelf:查看elf文件的工具editbin可更改DLL基地址修饰后符号名称解析binutils中的c++filt可用来解析被gcc修饰过的符号名称Windows API “UnDecorateSymbolName”可解析被Visual C++编译器的名称修饰规则修饰的符号C++ 代码会自动定义一个宏__cplusplus,可用来解决可能在 C 或 C++ 代码中使用的C库头文件的兼容问题,C++引用C库函数,须在函数声明前加extern "C"强符号:函数和初始化了的全局变量弱符号:未初始化的全局变量__attribute__(weak)将某符号强制性的变为弱符号强符号不能被重定义,但允许存在多个与其同名的弱符号。多个同名的弱符号可以并存,引用时实际使用强符号或占用空间最大的弱符号强引用必须有定义弱引用可没有定义,为定义的弱引用默认值为0,或一个特殊值ABI:指与符号修饰标准、变量内存布局、函数调用方式等跟可执行代码二进制兼容性相关的内容VC 编译预处理指令#pragma data_seg("foo")。。。pragma后定义的变量将全部放入foo段中,除非用另一条pragma预处理指令进行了段切换装载时重定位的动态链接方式,执行速度快,但共享对象无法实现进程间共享地址无关代码,执行速度慢,但可实现进程间共享,地址无关代码一般通过间接跳转的.got段实现动态加载存在同名符号覆盖的情况,此现象称为全局符号介入,因此可能引起程序逻辑错误程序运行中几个比较难发现的逻辑错误1、由于使用了不同版本的编译器,导致ABI不兼容,如不同版本编译器堆栈结构、符号修饰规则、调用习惯、数据结构内存分布、对齐方式等存在差异2、动态链接时发生了未预料的同名符号覆盖3、在多线程程序中使用了非线程安全的函数4、编译器过度优化,更改指令执行顺序(使用volatile解决)5、CPU 乱序执行导致程序异常(使用barrier解决)6、共享库内分配的内存在共享库外释放,或相反的方式,Linux 共享库命名规则:libname.so.x.y.zx:主版本号,表示重大升级,存在不兼容更新y:次版本号,表示增量升级,如添加新的接口功能,为兼容性更新z:分布版本号,表示只有一些错误修正,性能改进等,为兼容性更新libname.so.x又称为共享库的SO-NAMELinux系统为每一类兼容的共享库创建一个以SO-NAME为文件名的软链接命令行中使用的几个可改变动态链接器行为的环境变量添加共享库优先搜索路径LD_LIBRARY_PATH=/home/user cmd预先加载的共享库,可引起链接时同名符号覆盖LD_PRELOAD输出动态链接过程,可以去下列值:files、bindings、libs、versions、reloc、...、allLD_DEBUGgcc编译的共享库,默认情况下没有SO-NAME,可通过-Wl,-soname,myname参数指定DLL导出函数可通过在传统的函数定义前加__declspec(dllexport)来导出,而不用def文件,使用导出函数时在传统声明前加__declspec(dllimport)MSVC中C语言的默认调用规范为_cdecl,不对函数进行符号修饰,__stdcall为windows的通用调用规范,会对符号进行修饰,如:_Sub@16DLL的代码并非地址无关,因此不一定能被多个进程共享,即不一定支持一份代码多进程地址空间映射DLL优化如果知道DLL被加载的位置,使用更改DLL基地址的方法可以免去重定基地址,以提高程序的加载速度使用序号作为导入导出符号的手段,可免去动态链接时导出符号的二分查找导入函数DLL绑定,可免去动态链接时的符号解析,但DLL更新后或重定基地址后可能导致绑定失败。C++编写动态库注意事项:所有接口函数应该都为抽象的全局函数使用extern "C"来防止名字修饰,导出函数使用__stdcall调用规范不使用STL库、异常、虚析构函数不在DLL中申请内存而在DLL外释放内存或相反的方式,因为不同的DLL和可执行程序使用不同的堆接口不使用重载方法COM的主要目的之一是解决C++动态库的ABI兼容性问题不到万不得已,不要将大尺寸的对象或结构变量直接通过函数返回值返回,对象或结构变量的返回在实际实现上是通过两次内存拷贝完成的,效率不高线程的私有空间:栈、寄存器、TLS(线程局部存储,一般在进程堆中分配)静态链接C语言标准库crt时,如果通过ExitThread退出线程,线程私有数据_tidata将不会被释放,从而导致内存泄漏,因此最后使用经过包装后的线程函数,如C语言库的__beginthread,_endthreadLinux的每个进程都有自己的内核栈和用户栈 (收起)2011-12-08 13:25:47 回应
-
可执行文件的格式
jermaine (开始豆瓣)
.text和.data段分开有若干个好处: 1. 可以对code段写保护。 2. 多个进程可以共享code段。 3. locality .bss段并不需要存储数据,因为在这个段中的变量全部是未初始化的全局变量或者局部静态变量。有时候编译器也会将初始化为0的静态变量放在bss段。 (更多).text和.data段分开有若干个好处:1. 可以对code段写保护。2. 多个进程可以共享code段。3. locality.bss段并不需要存储数据,因为在这个段中的变量全部是未初始化的全局变量或者局部静态变量。有时候编译器也会将初始化为0的静态变量放在bss段。 (收起)2011-12-28 13:50:47 回应
书评 · · · · · · (共44条) 我来评论这本书
热门评论 最新评论
推荐linux c/c++程序员一读
-
- zoufeiyy 关于《程序员的自我修养》这本书,最初是在和博文的周筠老师MSN上谈起,当时听周老师提及这本书是一本关于链接和装载等系统软件知识的书籍,当时就很感兴趣,因为这方面的书在国内真的见得很少,一方面这种书似乎跟做应用开发的有距离,毕竟如果只是用用C#、Java,似乎没什么必要关心编译器、链接器在做些什么,特别是那么“老土”的C...... (19回应)2009-05-20 50/50有用
平中见奇:程序员提升自己的参考方法
-
- Stanley(羞涩而无畏,谦卑而执着) 老实说,在2002年还在上大学的时候,我把技术类书籍分成了三六九等,从值得看到最不值得看到顺序如下: 1. 在美国工作的中国人使用中文编写的书籍:因为作者的眼界相比国内更加宽广,而字里行间流淌着中国人的思维方式,没有理解文化表达方面的障碍,行文相对活泼 2. 在美国工作的人使用英文编写的书籍 3. 在中国工作的人...... (11回应)2009-06-27 43/44有用
给每个新手的修养之道
-
- 落落左痕 如果你是高手,Linux Hacker或者geek,请绕行 但如果你是新手 如果你曾好奇过windows系统目录下和软件目录下大堆大堆的dll文件是什么 如果你曾疑惑过我写下的代码经历的怎样的历程最后怎样到达了内存,编译器每天用,它到底做了什么 如果你已经学习或接触了C,汇编,计算机结构,但还是没办法把三者的关...... (16回应)2009-11-28 20/24有用
something after read
-
- 张学成 今天花了一天的时间从头到尾翻了一遍, 跳过了那些有X86汇编的部分, 和分析C++ CRT中解构析构的部分, 其他的都读了一遍. 读完之后唯一的感觉就是: 此书非读不可, 而且要经常读. 毫无疑问作者对于链接, 装载和库这三个方面是有深刻的认识的, 于深度和广度都无可挑剔, 而且组织文字的能力也属上乘, 虽...... (5回应)2009-11-17 13/13有用
提高自我修养,成为卓越的程序员
-
- 牧南(生命是荷叶上的一滴露珠。) 从大一学编程到现在已经好几年了,说来惭愧,一直用集成开发环境(IDE,如Visual Studio)编程,结果对程序从编写完到运行之间的过程并不明白。依稀记得老师讲过编译、汇编、链接,但究竟是怎么回事,我也说不清楚。 前几天突然意识到,正是使用IDE使我形成了惰性:点击一下“Build",生成可执行文件,一次......2011-01-19
书才出来的时候就很翻过几次,不过没买
-
- Negatlov(爱,是用来给予的!) 今天尽然无意中看到电子版出来了,很有点感慨,时间过的很快。当时很感兴趣,却无法深入理会,很多内容都看不明白。现在转到mac osx平台下了,windows的东西本以为可以暂时放下了,现在又见这本书,心中却是很舍不得。 书是一定要读得,难道国内能出这么本又质量得,题材较偏得书。比大多数这抄那抄,3月一本新书,错字错义无......2011-01-16
"程序员的自我修养"的论坛 · · · · · ·
| 知其然,更知其所以然——潘爱民 | 来自叶卡 | 3 回应 | 2011-11-21 |
| 对于本科生来说看了绝对是质的变化。 | 来自叶卡 | 2009-05-14 | |
| 博文视点致力原创——春播夏长,期待辉煌 | 来自博文视点 | 2009-06-05 | |
| C程序员的自我修养? | 来自satoru’ | 1 回应 | 2009-05-03 |
| 《程序员的自我修养》导读 | 来自博文视点 | 2009-04-23 |
> 浏览更多话题
在哪儿买这本书? · · · · · ·
以下豆列推荐 · · · · · · (全部)
- 给坏孩子看的计算机技术书 (baozii)
- 博文视点原创精品图书 (博文视点)
- IT技术 (Divine)
- 计算机理论 (mashan_snail)
- 计算机好书推荐 (sunlight)
谁读这本书?
喜欢这本书的人常去的小组 · · · · · ·

- 博文视点交流组 (420)

- KanRSS.com (480)

- Vim (6194)

- 程序设计语言 (1833)

- LISP (2010)

- Python编程 (18998)

- 程序员书屋 (6485)

- Hadoop China (889)
喜欢这本书的人关注的活动 · · · · · ·
订阅关于程序员的自我修养的评论:
feed: rss 2.0











