Unix/Linux系统编程自学笔记-第二章:编程背景
第二章笔记-编程背景
-
Linux中的文本编辑器与使用方法
- vim
vim有三种不同的操作模式:命令模式、插入模式和末行模式- 命令模式
默认状态,用来输入命令一般,大部分按键都有特定的功能。
比如hjkl这四个键,依次表示将光标向左、下、右、上移动一个字符或一行。
通过vim filename`进入文本后就是这个状态了 - 插入模式
用来输入和编辑文本,对应的按键是i(insert插入)和a(add追加) - 末行模式
用来退出或保存文件。
:w
:保存文件;
:q
:退出vim
:wq
:保存并退出
:q!
:强制退出,不保存,这个选择因为vim的保护机制,基本没用,想要强制退出还需要一些 WYSIWYG编辑器中常见的快捷键。 - WYSIWYG(所见即所得)快捷键
Ctrl+C:终止或退出,最有用,可以代替:!q
了;
Ctrl+K:删除行到缓冲区,暂时不知道怎么用这个;
Ctrl+Y:从缓冲区内容中复制或粘贴,与Ctrl+K配合使用的吧;
Ctrl+S:保存文件,大部分编辑器都有类似功能,保存。
- 命令模式
- gedit
书上略过,没有学习使用的要求,略。 - emacs
另一款Linux的编辑器,从效果来看与许多IDE类似,没有深入的学习。
- vim
-
程序开发
Linux下C程序开发过程的介绍,包括:- 用文本编辑器创建一个C源程序
vim hw.c
,输入代码 - 用gcc把源文件转为二进制可执行文件如:
gcc hw.c
,这时可执行文件将会被命名为a.out。
gcc的工作原理简要来说是向调用C编译器,把.c文件转换成包含机器汇编代码的.s文件,再把.s汇编代码经汇编器转化成二进制机器码,生成的文件格式是.o,所有的.o文件都包含了- 一个文件头,包括了代码段、数据段和BSS段的大小。
- 一个代码段,包含了机器指令。
- 一个数据段,包含了初始化全局变量和初始化静态局部变量。
- 一个BSS段,包含了未初始化的全局变量和未初始化的静态局部变量。
- 代码中的指针以及数据和BSS中的偏移量的重定位信息。
- 一个包含了非静态全局变量、函数名称和属性的符号表
- 链接。一个程序可能包含了多个相互依赖的.o文件,此外,它们还要调用C函数库,所以还要将这些函数源文件中不存在的函数与之组合成单一的二进制可执行文件a.out。运行a.out文件,程序即可运行。
关于链接方式,有静态链接和动态链接两种,静态链接将所有的必要的库函数和数据都纳入a.out文件中,使得它变的很大。而动态链接则使用共享库,将调用函数以指令的形式包含在a.out文件中,所以使用动态链接的a.out文件较小,许多的执行程序可在内存中共享相同的库函数,节省内存;修改库函数不必重新编译源文件。 - 可执行文件
包括二进制可执行平面文件、a.out可执行文件和ELF可执行文件;a.out文件是要介绍的重点内容。 - a.out文件的内容
- 文件头,包含了a.out文件的加载信息和大小,tsize表示代码段大小,dsize表示包含初始化的全局变量和初始化的静态局部变量数据段的大小,bsize表示了未初始化的全局变量和未初始化的静态局部变量的bss段的大小,total_size表示加载的a.out文件的总大小。
- 代码段,也叫正文段,包含了程序的可执行代码。从标准的C启动代码crt0.o开始,这一代码调用的是main()函数,这也是为啥一个C程序只能有一个main()函数。
- 数据段,包含了初始化全局变量和初始化静态局部变量的数据。
- 符号段,可选部分,仅在运行调试时有用。
- 程序执行过程
过程如下:- 读取a.out文件大小,确定所需内存空间及堆栈大小;
- sh从总大小中分配内存给执行映像;
- sh放弃旧映像,执行新映像;
- 执行从crt0.o开始,调用main()函数,将argc和argv作为参数传递给main(),argc为命令行参数数量,argv[指向对应的命令行参数和参数字符串。
- 用文本编辑器创建一个C源程序
-
程序终止
当代码出错,导致程序无法正常完成时就有用了。一般正常程序会自然终止,这时mian()会返回到crt0.o,再调用exit(0)来终结程序,当程序出错时,可以使用如“Ctrl+C”从快捷键来终止程序,还可以kill -s signal_number pid
来终止程序。 -
C语言程序中的函数调动
这部分主要作为知识拓展,可以简单的概括为crt0.o -> main() -> A(par_a) -> B(par_b) -> C(par_c)
-
C语言与汇编代码的链接
cc -m32 -S a.c
==>a.s file
gcc -E name.c -o name.i
预编译过程,从.c到.i;
gcc -S nema.i -o name.s
编译,将预处理的C代码转化为汇编码;
gcc -C name.s -o name.o
转换为机器码
以上步骤可以将一个C源程序一步步转换为汇编码和二进制机器码,代码可以记为“E-S-C&iso”。 -
链接库
包括静态库和动态库- 静态链接库
gcc -c mysum.c
ar rcs libmylib.a mysum.o
gcc -static t.c -L. -lmylib
a.out
以上代码是一个使用静态库的过程,-L.表示指定当前目录,可修改为其它,-l表示指定链接库mylib,其中,并未指定前缀lib和后缀.a。 - 动态链接库
gcc -c -fPIC mysum.c
gcc -shared -o linmylib.so mysum.o
gcc t.c -L -mylib
export LD_LIBRARY_PATH=./
a.out
与静态库类似,注意二者的不同之处。
- 静态链接库
-
makefile格式
makefile文件是由目标项、依赖项和规则组成。
make程序通过依赖项的时间戳来确定应构建哪些目标项,将会自动根据与之相关的最新依赖项来执行规则。
一个makefile示例:- 创建名为mk1的makefile:
myt: type.h t.c mysum.c
gcc -o myt t.c mtsum.c
- 指定mk1作为makefile运行make:
make -f mk1
make将构建目标文件myt,并将命令执行显示为:
gcc -o myt t.c mysum.c
- 再次运行make命令,将会显示如下内容:
make: 'myt' is up to date - 修改make文件,一般使用touch命令,使用如下sh命令:
touch type.h
make -f mk1
- 创建名为mk1的makefile:
-
GDB调试工具
介绍了基于emacsIDE的GDB调试方法,暂时用不上,但是调试方法值得学习。还提到了一些C语言中常出现的错误类型与处理方法:- 未初始化的指针或者错误的数值的指针,注意确保指针指向有效内存地址和非指向NULL;
- 数组下标越界,控制数组大小;
- 字符串指针和char数组使用不当,同上;
- assert宏,Unix系统中要注意它的使用;
- 使用fprintf()和getchar(),注意先进先出原则。
-
C语言数据结构
包括结构体、数据类型转换、链表和链表的操作、树、二叉树和二叉树的访问,还有Unix/Linux系统的文件系统管理编程项目,还没有做,这些都是基于之前数据结构课程的内容所涉及的数据结构的知识,现在看来,还是要好好的复习复习。