20145214 《信息安全系统设计基础》第2周学习总结
教材学习内容总结
通过VIMTUTOR实践教程了解VIM编辑器
-
h
:左移j
:下移k
:上移l
:右移 -
:q!
:退出编辑器,放弃所有改动 -
x
:删除光标所在位置的字符 -
i
:在光标前插入文本字符 -
A
:在一行后添加文本 -
:wq
:保存文件并退出 -
vim 文件名
:进入编辑器 -
dw
:从光标处删除至一个单词的末尾 -
d$
:从当前光标删除至行末 -
de
:从当前光标删除至单词末尾 -
d 数字 w
:删除数字个大写字母单词 -
dd
:删除该行2dd
:删除两行 -
u
:撤销最后执行的命令U
:撤销对整行的修改 -
CTRL + R
:恢复以前的操作结果 -
p
:将最后一次删除的内容置入光标之后 -
r + 字符
:替换光标所在位置的字符 -
cw
:改变文本直到一个单词的末尾 -
c$
:从光标处开始删除至行末
gcc编译器的基本原理
-
gcc 编译流程解析:预处理、编译、汇编、链接
-
Linux的可执行文件并没有像 Windows 那样有明显的.exe后缀名, 只需向其分配x(可执行)权限即可
sudo chmod u+x excutefile
-
gcc的-E参数可以让gcc在预处理结束后停止编译过程
-
gcc预处理源文件的时候(第一步),不会进行语法错误的检查。语法检查会在第二步进行,比如花括号不匹配、行末尾没有分号、关键字错误等
1)预处理阶段:在该阶段,对包含的头文件(#include)和宏定义(#define、#ifdef 等)进行处理。在上述代码的预处理过 程中,编译器将包含的头文件 stdio.h 编译进来,并且用户可以使用 gcc 的选项“-E”进行查看,该选项的 作用是让 gcc 在预处理结束后停止编译过程。
gcc –E hello.c –o hello.i
选项“-o”是指目标文件,“.i”文件为已经过处理的 C 程序。
(gcc 指令的一般格式为:gcc [选项] 要编译的文件 [选项] [目标文件] 其中,目标文件可缺省,gcc 默认生成可执行的文件,名为:编译文件.out)2)编译阶段:接下来进行的是编译阶段,在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。用户可以使用“-S”选项来进行查看, 该选项只进行编译而不进行汇编,结果生成汇编代码。
gcc –S hello.i –o hello.s
3)汇编阶段:汇编阶段是把编译阶段生成的“.s”文件转成目标文件,读者在此使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码了。
gcc –c hello.s –o hello.o
4)链接阶段:在成功编译之后,就进入了链接阶段。 系统把函数的实现都放到名为 libc.so.6 的库文件中去了,在没有特别指定时, gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 数库中去,这样就能使用各类函数了,而这也正是链接的作用。
函数库有静态库和动态库两种。静态库是指编译链接时,将库文件的代码全部加入可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后名通常为“.a”。动态库与之相反,在编译链接时并没有将库文件的代码加入可执行文件中,而是在程序执行时加载库,这样可以节省系统的开销。一般动态库的后名为“.so”,如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。 完成了链接之后,gcc 就可以生成可执行文件。
gcc hello.o –o hello
./hello
-
用gcc编译一个经典的c程序
-
gcc编译模块化的程序
gcc编译中的库选项
-
我们所编写的.c文件都可以制作一个函数库。过程如下:
-
a.静态库的创建和使用:使用归档工具ar将一些目标文件集成在一起。例如:
[root@localhost lib]# `gcc -c haha.c` [root@localhost lib]# `ar rcsv libpow.a haha.o` a - haha.o
下面编译主程序,它将会链接到刚生成的静态库haha.a:
[root@localhost lib]# `gcc -o heihei heihei.c -L. -lpow`
[root@localhost lib]# `./heihei 2 10`
2^10=1024
其中,选项“-L dir”的功能与“-I dir”类似,能够在库文件的搜索路径列表中添加 dir 目录,而“-lname” 选项指示编译时链接到库文件 libname.a 或者 libname.so。本实例中,程序heihei.c 需要使用当前目录下的一个静态库 libpow.a。
-
b.动态库(共享库)的创建和使用:首先使用gcc的-fPIC选项为动态库创造一个目标文件:
[root@localhost lib]# `gcc -fPIC -Wall -c haha.c`
接下来使用-shared选项和已创建的位置无关目标代码,生成一个动态库libpow.so
[root@localhost lib]# `gcc -shared -o libpow.so haha.o`
下面编译主程序,它将会链接到刚生成的动态库libpow.so
[root@localhost lib]# `gcc -o heihei heihei.c -L. -lpow`
-
在运行可执行程序之前,需要注册动态库的路径名。其方法有几种:修改/etc/ld.so.conf 文件,或者修改 LD_LIBRARY_PATH 环境变量,或者将库文件直接复制到/lib 或者/usr/lib 目录下(这两个目录为系统的默认的库路径名)。
[root@localhost lib]# `op libpow.so /lib` [root@localhost lib]# `./heihei 2 10 2^10=1024
-
动态库只有当使用它的程序执行时才被链接使用,而不是将需要的部分直接编入可执行文件中,并且一 个动态库可以被多个程序使用故可称为共享库,而静态库将会整合到程序中,因此在程序执行时不用加载静态库。 从而可知,链接到静态库会使用户的程序,并且难以升级,但是可能会比较容易部署。而链接到动态库会使用户的程序轻便,并且易于升级,但是会难以部署
gdb调试技术
-
gdb主要帮忙用户完成下面4个方面的功能:
1.启动程序,可以按照用户自定义的要求随心所欲的运行程序。 2.可让被调试的程序在用户所指定的调试的断点处停住 (断点可以是条件表达式)。 3.当程序停住时,可以检查此时程序中所发生的事。 4.动态地改变程序的执行环境。 5.从上面来看,gdb和一般的调试工具区别不大,基本上也是完成这些功能,不过在细节上,会发现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查看。
-
gdb调试:
$ gdb testgdb <---------- 启动gdb (gdb) break 16 <-------------------- 设置断点,在源程序第16行处。 (gdb) break func <-------------------- 设置断点,在函数func()入口处。 (gdb) info break <-------------------- 查看断点信息。 (gdb) r <--------------------- 运行程序,run命令简写 (gdb) n <--------------------- 单条语句执行,next命令简写。 (gdb) c <--------------------- 继续运行程序,continue命令简写。 Continuing. (gdb) p i<--------------------- 打印变量i的值,print命令简写。 (gdb) bt <--------------------- 查看函数堆栈。 (gdb) finish <--------------------- 退出函数。 (gdb) c <--------------------- 继续运行。 (gdb) q <--------------------- 退出gdb。
Makefile 使用
-
make工具最主要也是最基本的功能就是根据makefile文件中描述的源程序至今的相互关系来完成自动编译、维护多个源文件工程。而makefile文件需要按某种语法进行编写,文件中需要说明如何编译各个源文件并链接生成可执行文件,要求定义源文件之间的依赖关系
-
一个Makefile文件主要含有一系列的规则,每条规则包含一下内容:
一个目标,即make最终需要创建的文件,如可执行文件和目标文件; 目标也可以是要执行的动作,如‘clean’; 一个或多个依赖文件的列表,通常是编译目标文件所需要的其他文件。
-
之后的一系列命令,是make执行的动作,通常是把指定的相关文件编译成目标文件的编译命令,每个命令占一行,并以tab开头(初学者务必注意:是tab,而不是空格),执行以上Makefile后就会自动化编译。
教材学习中的问题和解决过程
问题1:dw
和de
有什么区别
-
解决:
dw
删除一个单词(包括空格);de
删除一个单词(不包括空格)。如图: -
当光标位于单词some的首字母s时
-
用
dw
会将整个单词some包括some后的空格一同删除
-
用
de
只能删除单词some,使得单词a和单词words之间出现两个空格
问题2:输入2w
,3e
时光标都向后移动,而不是如教程中说的“输入2w使光标向前移动两个单词,输入3e使光标向前移动到第三个单词的末尾”
- 解决:查询资料后发现,
w
和e
操作的共同的基本功能是使光标右移,所以2w
和3e
输入后光标后移是正确的,此处教程出错。
问题3:静态库的使用: gcc -o main main.c -L. -lxxx
中-L
, -l
的含义
- 解决:选项“-L dir”的功能与“-I dir”类似,能够在库文件的搜索路径列表中添加 dir 目录,而“-lname” 选项指示编译时链接到库文件 libname.a 或者 libname.so。
练习中的问题和解决过程
-
输入所有代码并gcc编译运行代码
-
发现运行结果中少了一个功能
-
检查错误发现main函数中少打了一行printf的代码
-
最终得到正确的结果
-
把上述代码中除了main函数外的代码制作成一个静态库math.a时一开始出现错误,后来发现是因为没有用
gcc -c
先生成静态库
-
制作共享库math.so
-
编写makefile,让代码编译,上述静态库和共享库的使用自动化
ubuntu中托管代码出现的问题和解决过程
-
参照卢肖明同学写的教程首先查看了是否已经安装git
-
发现git已经安装完毕后按着教程继续往下做
-
之后出现了被拒绝登录的情况
-
仔细检查发现配置时将
user.email
误打成了user.eamil
-
于是查看git所有配置项
-
重新配置并继续往下做
-
又出现了fetch-first的错误
-
由于这个错误在windows下托管代码时已经遇到过,所以轻松解决
本周代码托管截图及行数统计
其他(感悟、思考等,可选)
- 本周首先学习的vi命令行模式功能键,由于功能实在太过强大,虽然练习了一遍教程,但是只能记住一些较为常用的操作键,并且在学习的过程中发现使用功能键时需要特别小心,因为有时字母的大写和小写实现的功能会天差地别,比如命令行模式下
x
可删除光标所在的字符,而X
删除的是光标所在的前一个字符,这样微小的差别有时很难注意到,因此我认为最重要的是掌握回到上一步功能——u
。 - 这一周的学习内容不仅有电子版还有教材上的内容,感觉学习的内容比较杂,只能看着学习指导一个知识点一个知识点的学,比较没有系统性。
- 通过在ubuntu上托管代码,深刻的感受到虽然系统不同,但是还是和windows下托管代码有很多的共通之处,更能理解娄老师上课所说的元知识是为何物,也更能体会到老师让我们用不同的工具学习的良苦用心!
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 100/100 | 1/2 | 20/20 | |
第二周 | 76/176 | 1/3 | 30/50 |