国内最全IT社区平台 联系我们 | 收藏本站
华晨云阿里云优惠2
您当前位置:首页 > php开源 > php教程 > 程序员的自我修养读书笔记

程序员的自我修养读书笔记

来源:程序员人生   发布时间:2016-07-01 15:30:06 阅读次数:2528次

1.进程直接使用物理内存的坏处:第1、地址空间不隔离,1个进程可能改写另外一个进程的数据,从而致使系统崩溃。第2、内存使用效力低,频繁的数据换入换出,效力低。第3、程序运行地址不稳定,每次重新装载的空闲区域位置不肯定。

2.虚拟地址和物理地址是为了隔离进程。

3.分段使用1段虚拟空间和物理空间的映照解决了地址空间隔离和程序运行地址稳定的问题。但是内存使用效力由于内存不足时换入换出到磁盘的还是全部程序,因此会有大量的磁盘访问操作,粒度比较大。程序在运行时候,常常只会访问部份数据,大部份数据是不会被频繁的使用的,因此将粒度更小化,局部性原理得到利用,就有了分页机制。

4.Linux中的缺页异常机制,其实这本质上是1种动态分配内存的机制,然后每一个页有自己的属性,利用MMU来进行页映照。

5.线程是轻量级的进程,1个标准的线程是由线程ID、当前指令指针PC、寄存器集合和堆栈组成,线程同享程序的内存空间,包括代码段,数据段,堆等。

6.多线程的好处:多线程可以有效利用1个线程等待的时候去做其他的事情;长时任务,1个线程负责计算,1个线程负责交互;适应多核或多cpu计算机;同享数据效力高。

7.线程私有数据为局部变量、TLS局部存储、函数参数,同享的为全局变量、堆数据、函数静态变量、程序代码和打开的文件。

8.线程的状态有运行、就绪和等待。

9.频繁计算的线程叫CPU密集型线程,频繁等待的线程叫I/O密集型线程,后者相对来讲更加受欢迎。

10.fork和execl,写时复制机制,LDDR3讲的很清楚。

11.i++这个指令转化成汇编的时候不只是1条指令,因此有可能在履行到1半的时候被打断,单指令操作叫做原子操作。

12.临界区的作用范围仅限于本进程,其他的进程没法获得该锁。其余性质和互斥量基本相同。

13.1个函数可重入,表示这个函数没有履行完成,由于外部因素或内部调用又1次进入函数履行,1个函数要被重入,有两种情况:第1、多个线程同时履行这个函数。第2、函数本身(多是经过量层调用以后)调用本身。

14.可重入的特点。。。,保障并发安全。

15.volatile关键字可以制图组织过度优化,这个在很多寄存器操作中用到过。

16.linux内核代码中使用了众多的if语句,这里得到解释,原来是可以将lock的调用开消下降到最小,具体为何,后期琢磨。

17.barrier指令是用于禁止cpu将该指令之前的指令交换到以后,linux内核源码中也见到过。

18.1对1的线程模型让多线程程序在多处理器的系统上具有更好的表现,但是内核限制内核线程的数量,1对1线程会让用户的线程数量遭到限制,另外上下文切换开消较大,

19.多对1的线程模型可以具有无尚限的线程,上下文切换效力高,但是多处理器性能不会有明显提升,并且当1个阻塞,其余的都会阻塞。


1.gcc是后台程序的包装,不同的语言调用不用的预编译和编译工具。

2.重新计算各个目标地址的进程叫做重定位。

3.符号被用来表示表示1段子程序(函数)或变量的起始地址。汇编语言中jmp等指令可以理解为符号?

4.预编译、编译、汇编和链接。

5.动态链接库和静态链接库都依照可履行文件进行存储。

6.程序源代码编译后的机器指令寄存在代码段,.test或.code,全局变量、局部静态变量寄存在.data段,未初始化的全局变量、局部静态变量寄存在.bss段(预留),目标文件的开头包括段属性,文件内的偏移地址,还有每一个段的信息。

7.指令和数据分离的好处:第1、数据和指令的权限不同。第2、支持数据缓存和指令缓存。第3、节省内存。

8.readelf和obkdump工具的使用。

9.编译器的优化屏蔽了1些细节,对了解系统工作机制和调试有1定的影响。

10..bss段寄存的是未初始化的全局变量和局部静态变量,.data寄存了初始化的全局静态变量和局部静态变量。

11.有时希望函数中的局部变量的值在函数调用结束后不消失而保存原值,即其占用的存储单元不释放,在下1次该函数调用时,该变量保存上1次函数调用结束时的值。这时候就应当指定该局部变量为静态局部变量(static local variable)。 把局部变量改变成静态变量后是改变了它的存储方式,即改变了它的生存期。把全局变量改变成静态变量后是改变了它的作用域,限制了它的使用范围。

12.马屁股决定航天飞机的宽度的故事,遗留问题。

13.链接的进程实际上是对地址的援用,即对函数和变量地址的援用,所谓符号就是函数和变量的名称,符号值就是他们的地址。可使用nm来查看符号。

14.ELF文件中的符号表是1个段,名称为.symtab。

15.readelf –s xxxx.o查看符号在符号表中的状态。

16.使用ld来链接的时候,会自动定义1些特殊符号,例如程序起始地址,代码段结束地址,数据段结束地址等。

17.编译后的符号前后加上_是为了解决符号名冲突的问题,后来使用“签名机制”解决该问题。

18.extern “C”是表示编译器依照C规则进行编译。

19.强符号、弱符号,强援用和弱援用概念。

20.gcc –g添加调试信息。

21.链接器采取两步链接方法,行将各个目标文件中相同的段进行合并,再链接成1个大的目标文件。第1步:空间与地址分配(虚拟地址,注意BSS段)。第2步:符号解析与重定位。重定位进程最重要!

22.ld a.o b.o –e main –o ab,-e指定程序的入口为main函数,ld默许的为_start。

23.符号解析的肯定是通过分配得各个段的起始虚拟地址加上偏移量来的,(操作系统中,偏移量的使用无处不在啊)

24.重定位表被用来保存与重定位相干的信息,.rel.text,也叫重定位段,链接器根据这个重定位符号。

25.符号的解析占据了链接进程的大部份。

26.undefined reference xxxx1般都是由于链接时候缺少了某个库,或输入目标文件路径不正确或符号的声明与定义不1致。

27.指令修正,绝对地址和相对地址,分别为S+A和S+A-P,绝对地址为该符号的实际地址,相对地址为与符号与被修正地址的地址差。

28.common块机制处理弱符号解析的问题。

29.API是源码级别的利用程序接口,例如POSIX。ABI是2进制文件层面的接口,规范更加严格。

30.静态库可以简单地看作1组目标文件的集合。

动态链接

31.GCC手册内嵌汇编知识

32.Ld连接器的语句分为连接语句和赋值语句。

33.BFD库将编译器和链接器与目标文件格式隔离开。

34.Runtimelib运行时动态库。

35.程序的局部性原理,将运行的部份装载。

36.覆盖载入在初期内存不够用的时候用的较多,现在已很少使用,但是在DSP中或许还有用武之地。关键词:制止树间调用和明确调用路劲。

37.为何叫映像文件,由于可履行文件在装载的时候是被映照到虚拟地址空间的。

38.Linux缺页异常机制。do_page_fault(),建立可履行文件头文件和操作系统进程虚存之间的关系。当访问该内存时候,发现为空,则产生缺页异常。

39.对相同权限的段,把他们合并到1起当作1个段进行映照可以有效地减少系统内存的碎片。

40.从链接角度,依照section划分,链接视角;从装载角度,依照segment划分,履行视角。

41.Linux装载进程,./可履行文件以后,工作台调用fork,然后fork调用execve,这时候候工作台等待fork返回并接受用户输入的参数。:fork()->execve()->sys_execve()->do_execve()->search_binary_handler...。利用魔术肯定文件的格式和类型.

42.静态链接的缺点:浪费内存和磁盘空间,由于每一个1个进程都有自己用到的库的拷贝副本。第2是影响程序的跟新和发布,1个lib模块的更新,全部程序都要更新发布。

43.动态链接的优势:减少内存,减少物理页的换入换出,增加CPU缓存的命中率,升级容易,下降耦合率,增加程序的可扩大性和兼容性。缺点在于需要完善的同享库管理机制。linux下为.so,windows下为.dll

44.静态库为链接时重定位,动态库为装载时重定位。

45.地址无关代码技术。。不怎样看得懂。

46.如果1个lib.so中定义了1个全局变量a,进程A和进程B都使用了这个全局变量,1方的修改不会影响另外一方,由于他们有各自的数据段副本,是数据段副本。。。但是同1个进程的两个线程,任何1边的修改另外一个是会遭到影响的。

47.通过延迟绑定优化动态链接的速度。ELF通过PLT来实现,具体实现函数为_dl_runtime_reslove。

48.动态链接器其实也是1个同享库,系统通过映照方式将其加载到进程的地址空间中,并将控制权交给他。动态链接库进行1些列链接以后,将控制权交给可履行文件的入口地址。

49..interp段指定动态链接器的路径。1般是1个软链接。.dynamic段保存了动态链接器所需要的各种信息,比如哪些同享对象,动态链接符号表的位置,动态链接重定位表的位置,同享对象初始化代码等。.symtab为静态链接符号表,动态链接符号表为.dynsym,其中之保存于动态链接相干的符号。231页

50.rel.dyn是动态库对数据援用的修正(数据段),.rel.plt是对函数援用的修正(代码段)。

51.elf.h包括了动态链接时候的辅助信息。

52.动态链接的步骤:启动动态链接器本身,装载所需要的同享对象,重定位和初始化。

53.动态链接器自举后,首先找到自己的GOT段,第1个寄存的是.dynamic段,找到自己的重定位表和符号表等。

54.同享对象全局符号参与指的是在两个模块定义了同1个符号的时候,其中1个将另外1个覆盖的现象,即他们之间存在优先级的顺序。Linux的LD采取的是,如果行将加入的符号和已存在的符号同名的话,就疏忽行将加入的这个符号。

55.动态链接器本身是静态链接的。也是PIC的(地址无关代码)。

56.运行时加载,显示模块加载,linux驱动insmod和rmmod。

57.对动态库的操作分为4个函数:打开(dlopen),查找符号(dlsym),毛病处理(dlerror),关闭动态库(dlclose)

58.Libname.x.y.z.so,x主版本号,y次版本号,z发布版本号

59.SO-NAME机制,去掉次版本号和发布版本号,建立软连接指向次版本号和发布版本号最新的库。

60.程序的运行环境包括,内存、运行库和系统调用。

61.栈1般分配在高地址内存区域,用来保存程序的上下文,它会向下生长。堆1般分配在低地址的内存区域,程序malloc和new出来的内存就在此分配,它是向上生长。

62.指针在初始化为NULL后,使用前1定要给他指向1个地址。栈上的指针也需要初始化好,不然随机指针会出现毛病。

63.栈保存了:函数返回的地址和参数;临时变量包括局部的非静态的局部变量和编译器生成的临时变量;保存的上下文包括函数调用前后需要保存不变的寄存器。

64.Ebp寄存器成为帧指针,固定在函数活动的位置,调用函数的时候首先将参数压入栈中,然后将下1条指令压入栈中,跳转到函数体履行。

65.函数的调用惯例:1.函数参数的传递方式温柔序,例如从左到右还有益用寄存器传递参数提高性能。2.栈的保护方式,主要是弹出的时候由栈本身完成还是有函数体自己完成。3.名字修饰策略。默许的在C语言中使用的是_cdec1。(318页)

31.eax用来传递函数的返回值。

32.堆空间由运行库先向操作系统批发,再向各个程序零售,当零售光了的时候运行库再向系统批发。运行库有保护堆空间的算法。分别为mmapbrk

33.在Linux2.6内核版本里,malloc可以分配的内存空间多达2.9G

34.Malloc申请的内存,在进程结束以后就不存在了,由于进程结束以后,进程的资源包括内存,打开的文件,网络接口等都会被操作系统回收。

35.堆的管理算法:简单的方法有:空闲链表,位图。针对固定分配大小的内存,可使用对象池。1般会采取多种方法的综合。

36.Main函数之前会运行入口函数或叫入口点,操作系统在创建进程后,将系统的的控制权交给了程序的入口,入口函数都程序运行环境和运行库进行初始化,包括堆、I/O、线程、全局变量等等。

37.入口函数初始化结束以后,调用Main函数,main函数履行结束返回到入口函数,然后回收资源,进行清算工作。

38.环境变量存储的是1些系统的公然信心,例如路劲,版本等。

39._start传给main的参数除argcargv里面的参数意外,还包括initmain调用前的初始化工作;fini:main结束后的扫尾工作。Rtld_fini:和动态加载有关的扫尾工作。

40.其实main函数的退出也隐式的调用了exit函数,在exit后面还有个hlt是为了避免exit没有调用,强迫的把进程给干掉。

41.程序的I/O包括文件、管道、信号、网络、命令等。

42.I/O对文件的操作,初始化主要包括:建立打开文件表,如果能够继承自父进程,那末从父进程获得继承的句柄,初始化标准输入输出。

43.C语言的运行库大致包括以下功能:1.启动与退出。2.标准函数。3.I/O4.堆的封装和实现。5.语言实现。6.调试功能

C语言的标准库由美国国家标准协会制定,最后1次扩充是1999年。。


66.(374)

67.线程私有数据包括:局部变量,函数的参数,线程局部存储的数据。线程同享的数据包括:全局变量,堆上的数据,函数里面的静态变量,程序代码和打开的文件。

68.printf/fprintf在被多线程同享使用时,也会造成混乱。C库当中1些函数做成可重入的。

69.可重入函数主要用于多任务环境中,1个可重入的函数简单来讲就是可以被中断的函数,也就是说,可以在这个函数履行的任什么时候刻中断它,转入OS调度下去履行另外1段代码,而返回控制时不会出现甚么毛病。

70.由于glibc在malloc和new中支持了多线程,所以在使用前后不用加锁。但是1些例如memcopy,还是需要做保护。

71.缓冲机制的目的是为了不减少系统调用或读盘的次数,减少切换开消,framebuffer,还有等等都是这样。

72.linux下fread的实现:

73.linux下使用int 0x80来动身所有的系统调用。例如fork以后,会产生int 0x80的中断,然后去查找中断向量表,会发现是sys_call,这时候候fork的系统调用好会寄存在eax中,再去比对系统调用号的表,找到sys_fork,履行后返回到用户态。

74.ESP是栈指针寄存器,指向系统栈最上面1个栈的栈顶。

75.EBP是基址指针寄存器,指向系统栈最上面1个栈的底部。

76.EAX1般用来保存函数的返回值,EB/C/DX等1般用来传递参数。

生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠
程序员人生
------分隔线----------------------------
分享到:
------分隔线----------------------------
关闭
程序员人生