《Expert C Programming》阅读笔记
从接触Linux开始,一直学习并使用C语言,C语言与Linux是相辅相成的。从刚开始对C的了解学习到慢慢熟练使用,渐渐认识到C的精妙,C语言比较贴合底层硬件,要求编码时对程序更精确的掌控。
通过阅读《C专家编程》,对C语言的理解包括编译等都有了更深刻的了解,C强调一切由程序员实现,编码时需要保证自己程序的准确,《C专家编程》给我最有意义的认识是:在编码时更清楚程序的运行细节,从底层硬件及Linux系统函数实现的角度更深入的认识了高质量编码。
书中通过实例讲解,并给出编程挑战,阅读跟实践相结合,加深了对内容的理解,编程实现的同时让人有茅塞顿开的感觉。下面总结几个印象最深刻的知识点:
一. 程序运行时的数据结构:
清楚的了解了可执行程序的各个段(文本段、数据段、bss段),以及其在内存中的布局(如下图)。
1.编译“hello world”程序,在可执行文件中执行ls -l,得到文件的总体大小。运行size得到文件里各个段的大小。
2.增加一个全局的int[1000]数组声明,重新进行编译,再用上面的命令得到总体及各个段的大小。可以清楚看到增加全局的未初始化的int数组,都保存在bss段。
3.现在,在数组的声明中增加初始值(C语言并不强迫对数组进行初始化时为每个元素提供初始值)。可以看到初始化全局数组后,使数组从BSS段转换到数据段。
4.在函数内声明一个巨大的数组。然后再声明一个巨大的局部数组,最后在加入一个函数,并在函数内部声明一个大数组。可以看到后面增加的局部大数组声明都布局在文本段。
二.对内存的思考
阅读此章节后,对Intelx86的内存工作原理以及MMU都有了进一步的理解,并对linux本身的系统函数实现及贴合硬件的优化进行了学习和了解(例如提到的memcpy函数的优化实现),总结一下印象比较深的几个知识点:
1.虚拟内存
a.虚拟内存 – 使用磁盘保存运行进程的映像,通过“页”的形式组织,页就是磁盘和内存之间来回移动的单位
b.在磁盘上有个特殊的交换区,用来保存从内存中换出的进程
c.进程只能操作位于物理内存中的页面
2.Cache
a.Cache的操作速度域系统的周期时间相同
b.Cache包含一个地址的列表以及它们的内容,所有对内存的读取和写入都要经过cache
c.Cache采用写直达,写回法,保持命中
d.行Line是对Cache进行访问的单位,一个行内的数据成为块block
3.堆和数据段
a.堆中的所有东西都是匿名的,不能按名字访问,只能通过指针
b.堆内存的回收不必与所分配顺序一致,它甚至可以不回收
c.管理内存的调用:malloc、free、brk和sbrk(调整数据段的大小)
4.内存泄漏
a.堆经常出现两种类型的问题
b.释放和改写仍在使用的内存(内存损坏)
c.未释放不再使用的内存(内存泄漏)
每次malloc后,调用free释放它。或者,尽可能地使用alloca来分配,它会被自动释放掉。
5.总线错误
a.总线错误计划局都是由于未对齐的读和写引起的,而数据项是不能跨越页面或Cache边界的
b.编译器通过自动分配和填充数据来进行对齐
以上是自己在阅读笔记中总结的印象比较深刻的两个点,看《C专家编程》的同时,实例编码调试,从不同的角度、深度去理解了C编程的奥妙,还是比较有成就感的。书中很多有趣的IT历史事件,项目实例等也让我获益匪浅,总之,即使多了点滴认识,也是很愉快的:)。