学习目标:复习前面的Linux命令,Linux编程基础,教材前七章的内容 |
学习资源:书 |
学习任务:1. 复习Linux命令,特别是man -k, cheat, grep -nr xxx /usr/include 2. 复习vi, gcc, gdb,make的使用 3. 复习教材内容ch01 ch02 ch03 ch04 ch06 ch07 4. 复习前面的考题(答案解析见http://group.cnblogs.com/topic/73060.html) ,下次考试考每次考试错的最多的题目 5. 期中总结发一篇Blog: 知识点总结 自己的收获(不要假大空) 自己的不足(要具体,有改进措施) 课程建议和意见(要有理由) |
学习过程:
1.复习Linux命令,特别是man -k, cheat, grep -nr xxx /usr/include
(1)man是系统调用的,如open、write
使用带有-k选项的man命令可以根据关键字搜索联机帮助。例如要查找"sysctl"的信息,在命令中输入如下命令:
(1)cheat是在GNU通用公共许可证下,为Linux命令行用户发行的交互式备忘单应用程序。它提供显示Linux命令使用案例,包括该命令所有的选项和简短但尚可理解的功能。提供简单命令选项。
(1)Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来。grep全称是Global Regular Expression Print,表示全局正则表达式版本,它的使用权限是所有用户。[options]主要参数:
-c:只输出匹配行的计数。
-I:不区分大 小写(只适用于单字符)。
-h:查询多文件时不显示文件名。
-l:查询多文件时只输出包含匹配字符的文件名。
-n:显示匹配行及 行号。
-s:不显示不存在或无匹配文本的错误信息。
-v:显示不包含匹配文本的所有行。
pattern正则表达式主要参数:
\: 忽略正则表达式中特殊字符的原有含义。
^:匹配正则表达式的开始行。
$: 匹配正则表达式的结束行。
\<:从匹配正则表达 式的行开始。
\>:到匹配正则表达式的行结束。
[ ]:单个字符,如[A]即A符合要求 。
[ - ]:范围,如[A-Z],即A、B、C一直到Z都符合要求 。
。:所有的单个字符。
* :有字符,长度可以为0。
N:显示行号
R:递归查找
Xxx:所要查找的宏
2.复习vi, gcc, gdb,make的使用
(1)VI是unix上最常用的文本编辑工具
进入vi的命令
vi filename :打开或新建文件,并将光标置于第一行首
vi +n filename :打开文件,并将光标置于第n行首
vi + filename :打开文件,并将光标置于最后一行首
vi +/pattern filename:打开文件,并将光标置于第一个与pattern匹配的串处
vi -r filename :在上次正用vi编辑时发生系统崩溃,恢复filename
vi filename....filename :打开多个文件,依次编辑
移动光标类命令
h :光标左移一个字符
l :光标右移一个字符
space:光标右移一个字符
Backspace:光标左移一个字符
k或Ctrl+p:光标上移一行
j或Ctrl+n :光标下移一行
Enter :光标下移一行
w或W :光标右移一个字至字首
b或B :光标左移一个字至字首
e或E :光标右移一个字j至字尾
) :光标移至句尾
( :光标移至句首
}:光标移至段落开头
{:光标移至段落结尾
nG:光标移至第n行首
n+:光标下移n行
n-:光标上移n行
n$:光标移至第n行尾
H :光标移至屏幕顶行
M :光标移至屏幕中间行
L :光标移至屏幕最后行
0:(注意是数字零)光标移至当前行首
$:光标移至当前行尾
屏幕翻滚类命令
Ctrl+u:向文件首翻半屏
Ctrl+d:向文件尾翻半屏
Ctrl+f:向文件尾翻一屏
Ctrl+b;向文件首翻一屏
nz:将第n行滚至屏幕顶部,不指定n时将当前行滚至屏幕顶部。
插入文本类命令
i :在光标前
I :在当前行首
a:光标后
A:在当前行尾
o:在当前行之下新开一行
O:在当前行之上新开一行
r:替换当前字符
R:替换当前字符及其后的字符,直至按ESC键
s:从当前光标位置处开始,以输入的文本替代指定数目的字符
S:删除指定数目的行,并以所输入文本代替之
ncw或nCW:修改指定数目的字
nCC:修改指定数目的行
删除命令
ndw或ndW:删除光标处开始及其后的n-1个字
do:删至行首
d$:删至行尾
ndd:删除当前行及其后n-1行
x或X:删除一个字符,x删除光标后的,而X删除光标前的
Ctrl+u:删除输入方式下所输入的文本
搜索及替换命令 :
/pattern:从光标开始处向文件尾搜索pattern
?pattern:从光标开始处向文件首搜索pattern
n:在同一方向重复上一次搜索命令
N:在反方向上重复上一次搜索命令
:s/p1/p2/g:将当前行中所有p1均用p2替代
:n1,n2s/p1/p2/g:将第n1至n2行中所有p1均用p2替代
:g/p1/s//p2/g:将文件中所有p1均用p2替换
选项设置
all:列出所有选项设置情况
term:设置终端类型
ignorance:在搜索中忽略大小写
list:显示制表位(Ctrl+I)和行尾标志($)
number:显示行号
report:显示由面向行的命令修改过的数目
terse:显示简短的警告信息
warn:在转到别的文件时若没保存当前文件则显示NO write信息
nomagic:允许在搜索模式中,使用前面不带“\”的特殊字符
nowrapscan:禁止vi在搜索到达文件两端时,又从另一端开始
mesg:允许vi显示其他用户用write写到自己终端上的信息
最后行方式命令
:n1,n2 co n3:将n1行到n2行之间的内容拷贝到第n3行下
:n1,n2 m n3:将n1行到n2行之间的内容移至到第n3行下
:n1,n2 d :将n1行到n2行之间的内容删除
:w :保存当前文件
:e filename:打开文件filename进行编辑
:x:保存当前文件并退出
:q:退出vi
:q!:不保存文件并退出vi
:!command:执行shell命令command
:n1,n2 w!command:将文件中n1行至n2行的内容作为command的输入并执行之,若不指
定n1,n2,则表示将整个文件内容作为command的输入
:r!command:将命令command的输出结果放到当前行
(2)GCC使用
在使用GCC编译程序时,编译过程可以被细分为四个阶段:
预处理(Pre-Processing)
编译(Compiling)汇编(Assembling)
链接(Linking)。例如:
#include
int main(void)
{
printf ("Hello world, Linux programming!\n");
return 0;
}
然后执行下面的命令编译和运行这段程序:
# gcc hello.c -o hello
#
./hello
Hello world, Linux programming!
GCC需要调用预处理程序cpp,由它负责展开在源文件中定义的宏,并向其中插入“#include”语句所包含的内容;接着,GCC会调用ccl和as将处理后的源代码编译成目标代码;最后,GCC会调用链接程序ld,把生成的目标代码链接成一个可执行程序。
(3)
GDB是GNU开源组织发布的一个强大的UNIX下调试程序工具。或许各位比较喜欢那种图形界面方式的,像VC,BCB等IDE的调试,但如果你是在UNIX平台下作软件,你会发现GDB这个调试工具有比VC,BCB的图形化调试器更强大的功能。所谓“寸有所长,尺有所短”就是这个道理。
一般来说,GDB主要帮助你完成下面四个方面的功能:
1、启动你的程序,可以按照你自定义的要求随心所欲的运行程序。
2、可以让调试程序在你所指定的位置的断点处停止。
3、当程序停止时,可以检查此时你的程序中所发生的事情。
4、动态的改变你程序的执行环境。
从上面看来,GDB和一般的调试工具没有什么两样,基本上也是完成这些功能,不过在细节上,你会发现GDB这个调试工具的强大,大家可能习惯图形化的调试工具,但有时候,命令行的调试工具却有着图形化工具所不能完成的功能。
一般来说GDB主要调试的是C/C++程序。要调试C/C++程序,首先在编译时,我们必须要把调试信息加到可执行文件中。使用编译器(cc/gcc/g++)的-g参数可以做到这一点,如:
$ cc –g hello.c –o hello
$ g++ -g hello.cpp –o hello
如果没有-g,你将看不见程序的函数名,变量名,所代替的全是运行的内存地址。当你用-g把调试信息假如之后,并成功编译目标代码以后,让我们来看看如果用GDB调试它。
启动GDB的方法有以下几种:
1、 gdb <program>
program也就是你的执行文件,一般在当前目录下。
2、 gdb <program> core
用gdb同时调试一个运行程序和core文件,core是程序非法执行后core dump后产生的文件。
3、 gdb <program> <PID>
如果你的程序是一个服务程序,那么你可以指定这个服务程序运行时的进程ID。gdb会自动attach上去,并调试它。program应该在PATH环境变量中搜索到。
GDB启动时,可以加上一些GDB的启动开关,详细的开关可以用gdb –help来查看。下面只列举一些比较常用的参数:
-symbols <file>
-s <file>
从指定文件中读取符号表。
-se file
从指定文件中读取符号表信息,并把他用在可执行文件中。
-core <file>
-c <file>
调试core dump的core文件。
-directory <directory>
-d <directory>
加入一个源文件的搜索路径。默认搜索路径是环境变量中PATH所定义的路径。
(4)在 Linux环境下使用 GNU 的 make工具能够比较容易的构建一个属于你自己的工程,整个工程的编译只需要一个命令就可以完成编译、连接以至于最后的执行。不过这需要我们投入一些时间去完成一个或者多个称之为 Makefile 文件的编写。此文件正是 make 正常工作的基础。
make 是一个命令工具,它解释 Makefile 中的指令(应该说是规则)。在 Makefile文件中描述了整个工程所有文件的编译顺序、编译规则。
期中小结
3. 复习教材内容ch01 ch02 ch03 ch04 ch06 ch07
第一章
计算机系统是由硬件和系统软件组成的,它们共同协作以运行应用程序。计算机内部的信息被表示为一组组的位.它们依据上下文有不同的解释方式。程序被其他程序翻译成不同的形式,开始时是ASCII文本.然后被编译器和链接器翻译成二进制可执行文件。
处 理器读取并解释存放在主存里的二进制指令,因为计算机可以把大量的时间用于存储器、I/O设备和CPU寄存器之间复制数据,所以将系统中的存储设备划分成 层次结构--CPU寄存器在顶部,接着是多层的硬件高速缓存存储器、DRAM主存和磁盘存储器在层次模型中,位于更高层的存储设备比低层的存储设备要更 快,单位比特开销也更高。层次结构中较高层次存储设备可以作为较低层次设备的高速缓存。
操作系统内核是应用程序和硬件之间的媒介。
它提供三个基本的抽象:1)文件是对I/O的抽象;2)虚拟存储器是对主存和磁盘的抽象:3)进程是对处理器、主存抽象和I/O设备的设备最后,网络提供了计算机系统之间通信的手段。从特殊系统的角度来看,网络就是一种I/O设备。
第二章
计算机将信息按位编码,通常组织成字节序列。用不同的编码方式表示整数、实数和字符串。不同的计算机模型在编码数字和多字节数据中的字节排序时使用不同的约定。
C 语言的设计可以包容多种不同字长和数字编码的实现。虽然高端机器逐渐开始使用64位字长,但是目前大多数机器仍使用32位字长。大多数机器对整数使用补码 编码,而对浮点数使用IEEE浮点编码。在位级上理解这些编码,并且理解算术运算的数学特性,对于想使编写的程序能在全部数值范围上正确运算的程序员来 说,是很重要的。
在相同长度的无符号和有符号整数之间进行强制类型转换时,大多数C语言实现遵循的原则是底层的位模式不变。在补码机器上,对于一个W位的值,这种行为是由函数T2Uw和U2Tw来描述的。
第三章
在本章中,我们窥视了C语言提供的抽象层下面的东西,以了解机器级编程。通过让编译器产生机器级程序的汇编代码表示,我们了解了编译器和它的优化能力,以 及机器、数据类型和指令集。在第5章,我们会看到,当编写能有效映射到机器上的程序时,了解编译器的特性会有所帮助。我们还更完整地了解了程序如何将数据 存储在不同的存储器区域中。在第12章会看到许多这样的例子,我们需要知道个程序变量是在运行时栈中,是在某个动态分配的数据结构中,是在某个全局存储位 置中。理解程序如何映射到机器上,会让理解这些存储之间的区别容易些。
机器级程序和它们的汇编代码表示,与C程序的差别很大。在汇编语言程序中, 各种数据类型之间的差别很小。程序是以指令序列来表示的,每条指令都完成一个单独的操作。部分程序状态,如寄存器和运行时栈,对程序员来说是直接可见的。 本书仅提供了低级操作来支持数据处理和程序控制。编译器必须用多条指令来产生和操作各种数据结构,来实现像条件、循环和过程这样的控制结构。我们讲述了C 语言和如何编译它的许多不同方面。我们看到C语言中缺乏边界检查,使得许多程序容易出现缓冲区溢出。虽然最近的运行时系统提供了安全保护,而且编译器帮助 使得程序更安全,但是这已经使许多系统容易受到入侵者的恶意攻击。
第四章
我们已经看到,指令集体系结构,即ISA,在处理行为和如何实现处理器之间提供了一层抽象。ISA提供了程序执行器行为的一种顺序说明,也就是一条指令执 行完了,下一条指令才会开始。从IA32指令开始,大大简化数据类型、地址模式和指令编码,我们定义了Y86指令集。得到的ISA既有RISC指令集的属 性,也有CISC指令集的属性。然后,将不同指令组织放到五个阶段中处理,在此,根据被执行指令的不同,每个阶段中的操作也不相同。据此,我们构造了 SEQ处理器,其中每个时钟周期执行一条指令,它会通过所有五个阶段。
流水线化通过让不同的阶段并行操作,改进了系统的吞吐量性能。在任意一个给 定的时刻:多条指令被不同的阶段处理。在引入这种并行性的过程中,我们必须非常小心,以提供与程序的顺序执行相同的程序级行为。通过重新调整SEQ各个部 分的顺序,引入流水线,我们得到SEQ+,接着添加流水线寄存器,创建出PIIE―流水线。然后,添加了转发逻辑,加速了将结果从一条指令发送到另一条指 令,从而提高了流水线的性能。有几种特殊情况需要额外的流水线控制逻辑来暂停或取消一些流水线阶段。
在本章中,我们学习了有关处理器设计的几个重要经验:
1.管理复杂性是首要问题,想要优化使用硬件资源,在最小的成本下获得最大的性能。为了实现这个目的,我们创建了一个非常简单而一致的框架,来处理所有不同的指令类型。有了这个框架,就能够在处理不同指令类型的逻辑中共享硬件单元。
2. 我们不需要直接实现ISA。它的直接实现意味着一个顺序的设计。为了获得更高的性能我们想运用硬件能力以同时执行许多操作,这就导致要使用流水线化设计。 通过仔细设计和分析,我们能够处理各种流水线冒险,因此运行一个程序的整体效果,同用ISA模型获得的效果完全一致。
3.硬件设计人员必须非常谨 慎小心。一旦芯片制造出来,就几乎不可能改正任何错误了。开始就使设计正确是非常重要的。这就意味着要仔细地分析各种指令类型和组合,甚至那些看上去没有 意义的情况,例如弹出值到栈指针。必须用系统的模拟测试程序彻底地测试设计。在开发PIPE的控制逻辑中,我们的设计有个细微的错误,只有通过对控制组合 的仔细而系统的分析才能发现。
第六章
基本存储技术包括随机存储器(RAM)、非易失性存储器(即OM)和磁盘。RAM有两种基本类型。静态RAM(SRAM)快一些,但是也贵一些,它既可以 用做CPU芯片上的高速缓存,也可以用做芯片下的高速缓存。动态RAM(DRAM)慢一些,也便宜一些,用做主存和图形帧缓冲区。非易失性存储器,也称为 只读存储器(ROM)即使是在关电的时候,也能保持它们的信息,它们用来存储固件。旋转磁盘是机械的非易失性存储设备,以每个位很低的成本保有大量的数 据,但是访问时间比DRAM更长。固态硬盘(SSD基于非易失性的闪存,越来越变成旋转磁盘对某些应用的具有吸引力的替代产品。
一般而言,较快的 存储技术每个位的价格会更高,而且容量较小。这些技术的价格和性能属性正在以显著不同的速度变化着。特别地,DRAM和磁盘访问时间远远大于CPU周期时 间。系统通过将存储器组织成存储设备的层次结构来弥补这些差异,在这个层次结构中,较小、较快的设备在顶部,较大、较慢的设备在底部。因为编写良好的程序 有好的局部性,大多数数据都可以从较高层得到服务,结果就是存储系统能以较高层的速度运行,但却有较低层的成本和容量。
程序员可以通过编写有良好空间和时间局部性的程序来显著地改进程序的运行时间。利用基于SRAM的高速缓存存储器特别重要。
第七章链接似乎没学
自己的收获
实际上这次是做的最认真的一次。大概是因为之前一直糊弄,突然觉得这样糊弄也依然浪费时间,那不如学点东西。在学习过程中,我发现其实蛮有趣的。给了一定的信心。前面的命令,翻书,在虚拟机里找,百度找,感觉上了解了一些,应该还需要多做题。
自己的不足
基础太差
由于之前自己跟自己闹别扭而落下很多东西,学起来很吃力,要不起来前面章节的内容大概还需要一些时间。从头开始,重新认真看书,用之前的任务重新开始完成,我想期末之前应该会有好转。总之之后不想糊弄了。
课程建议和意见
我会慢慢赶上来的,至少老师都已经这么说了,我也得试着喜欢和努力的。
我在office里先编辑的,粘贴时会变得很奇怪。所以就直接不保留原来的格式了。