Linux 开发入门通关指南:Vim 操作 + GCC 编译 + 库文件详解
Linux中安装软件:
- 源码安装,不推荐
- 软件包安装,不推荐按
- 包管理器 yum(centos) apt /apt-get(ubuntu)
- 包管理器类似于应用商店
- 必须使用root权限安装到系统里,安装一次,任何人都可以使用
- 可以避免依赖缺失,版本兼容性等问题
yum具体操作
查看软件包
- 列举出有哪些软件包
- 软件包名称:主版本号.次版本号.源程序发⾏号-软件包的发⾏号.主机平台.cpu架构
yum list
安装软件
# centos
sudo yum install -y lrzsz
# ubuntu
sudo apt install -y lrzsz
卸载软件
# centos
sudo yum remove [-y] lrzsz
# ubuntu
sudo apt remove [-y] lrzsz
安装源
- centos安装源路径
ll /etc/yum.repos.d/
total 16
-rw-r--r-- 1 root root 676 Oct 8 20:47 CentOS-Base.repo # 标准源
-rw-r--r-- 1 root root 230 Aug 27 10:31 epel.repo # 扩展源
- ubuntu安装源路径
$ cat /etc/apt/sources.list # 标准源
$ ll /etc/apt/sources.list.d/ # 扩展源
vim编辑器
![[vim键盘图.png]]
vim模式
- 正常/普通/命令模式(Normal mode)
- 控制屏幕光标的移动,字符、字或行的删除,移动复制某区段及进⼊Insert mode下,或者到last line mod
- 插入模式(Insert mode)
- 只有在Insert mode下,才可以做⽂字输⼊,按「ESC」键可回到命令⾏模式。该模式是我们后⾯⽤ 的最频繁的编辑模式。
- 末⾏模式(last line mode)
- ⽂件保存或退出,也可以进⾏⽂件替换,找字符串,列出⾏号等操作。
- 在命令模式下"shift+:"即可进⼊该模式。要查看你的所有模式:打开vim,底⾏模式直接输⼊ :help vim-modes
vim基本操作
- 进⼊vim,在系统提⽰符号输⼊vim及⽂件名称后,就进⼊vim全屏幕编辑画⾯:
- vim test.c
- 进⼊vim之后,是处于[正常模式],你要切换到[插⼊模式]才能够输⼊⽂字
- [正常模式]切换⾄[插⼊模式]
- 输入 a,光标后移
- 输入 i,光标原地不动
- 输入 o,光标移动到下一行
- [插⼊模式]切换⾄[正常模式]
- 目前处于[插⼊模式],就只能⼀直输⼊⽂字,如果发现输错了字,想⽤光标键往回移动,将该字删除,可以先按⼀下「ESC」键转到[正常模式]再删除⽂字。当然,也可以直接删除。
- [正常模式]切换⾄[末⾏模式]
- 「shift+; 」,其实就是输⼊「:」
- 退出vim及保存⽂件,在[正常模式]下,按⼀下「:」冒号键进⼊「last line mode」,例如:
- :w(保存当前⽂件)
- :wq(输⼊「wq」,存盘并退出vim)
- :q!(输⼊q!,不存盘强制退出vim)
vim正常模式命令
- 移动光标
- vim可以直接⽤键盘上的光标来上下左右移动,但正规的vim是⽤⼩写英⽂字⺟==「h」、「j」、 「k」、「l」,分别控制光标左、下、上、右==移⼀格
- 按「G」:移动到⽂章的最后
- 按「 $ 」:移动到光标所在行的“行尾”
- 按「^」:移动到光标所在行的“行首”
- 按「w」:光标跳到下个单词的开头
- 按「e」:光标跳到下个字的字尾
- 按「b」:光标回到上个字的开头
- 按「#l」:光标移到该行的第#个位置,如:5l,56l
- 按[gg]:进⼊到⽂本开始
- 按[shift+g]:进⼊⽂本末端
- 按「ctrl」+「b」:屏幕往“后”移动⼀页
- 按「ctrl」+「f」:屏幕往“前”移动⼀页
- 按「ctrl」+「u」:屏幕往“后”移动半页
- 按「ctrl」+「d」:屏幕往“前”移动半页
- 删除文字
- 「x」:每按⼀次,删除光标所在位置的⼀个字符
- 「#x」:例如,「6x」表示删除光标所在位置的“后面(包含⾃⼰在内)”6个字符
- 「X」:⼤写的X,每按⼀次,删除光标所在位置的“前面”⼀个字符
- 「#X」:例如,「20X」表⽰删除光标所在位置的“前面”20个字符
- 「dd」:删除光标所在行==(剪切)==
- 「#dd」:从光标所在行开始删除#行
- 复制
- 「yw」:将光标所在之处到字尾的字符复制到缓冲区中
- 「#yw」:复制#个字到缓冲区
- 「yy」:复制光标所在⾏到缓冲区。
- 「#yy」:例如,「6yy」表示拷贝==从光标所在的该⾏“往下数”==6⾏⽂字。
- 「p」:将缓冲区内的字符贴到光标所在位置。
- 替换
- 「r」:替换光标所在处的字符
- 「R」:替换光标所到之处的字符,直到按下「ESC」键为⽌。
- 撤销上一次操作
- 「u」:如果您误执行⼀个命令,可以⻢上按下「u」,回到上⼀个操作。按多次“u”可以执行多次回复。
- 「ctrl+r」:撤销的恢复
- 更改
- 「cw」:更改光标所在处的字到字尾处
- 「c#w」:例如,「c3w」表示更改3个字
- 跳⾄指定的行
- 「ctrl」+「g」列出光标所在行的行号。
- 「#G」:例如,「15G」,表示移动光标至文章的第15行行首。
- 退出
- 「shift+zz」:保存并退出
- 查找单词
- 「shift+3」:查找当前光标所指向的单词
vim末行模式命令集
- 处于命令模式,再按「:」冒号即可进⼊末⾏ 模式
- 列出行号
- 「set nu」:输⼊「set nu」后,会在文件中的每一行前面列出行号
- 跳到文件的某一行
- 「#」:「#」号表⽰⼀个数字,在冒号后输⼊⼀个数字,再按回⻋键就会跳到该行了,如输⼊数字 15,再回车,就会跳到⽂章的第15行。
- 查找字符
- 「/关键字」:先按「/」键,再输⼊您想寻找的字符,如果第⼀次找的关键字不是您想要的,可以⼀直按「n」会往后寻找到您要的关键字为止。按「N」向前寻找
- 「?关键字」:先按「?」键,再输⼊您想寻找的字符,如果第⼀次找的关键字不是您想要的,可 以⼀直按「n」会往前寻找到您要的关键字为⽌。按「N」向后寻找
- 区别在于,/是从前往后寻找,?是从后往前寻找
- 保存文件
- 「w 」:在冒号输⼊字⺟「w」就可以将⽂件保存起来
- 离开vim
- 「q」:按「q」就是退出,如果⽆法离开vim,可以在「q」后跟⼀个「!」强制离开vim。
- 「wq」:⼀般建议离开时,搭配「w」⼀起使⽤,这样在退出的时候还可以保存⽂件
可视化模式
- 命令模式按照 ==ctrl+v ==进入可视化模式
- 用方向键(上、下、左、右)移动光标,选中需要批量编辑的矩形区域;
- 按下
I(大写的 i,代表块插入),此时会进入块插入模式,输入要添加的内容 - 输入完成后按
Esc,选中的所有行的对应列位置,会同步出现刚才输入的内容,完成批量编辑
编辑器gcc/g++
gcc编译选项
- 格式: gcc [选项] 要编译的文件 [选项] [目标文件]
- 记忆:选项:ESc(键盘退出),目标文件后缀 iso(映像文件)
不加选项
- gcc 文件名 [-o] [目标文件]
- 默认直接生成可执行文件a.out.如果写了 -o + 目标文件名会生成对应的可执行文件
gcc hello.c
预处理(进行宏替换)
- 本质就是修改代码
- 预处理功能主要包括宏定义,文件包含,条件编译,去注释等
- 预处理指令是以#号开头的代码行
- 示例:gcc –E hello.c –o hello.i
- 选项“-E”,该选项的作⽤是让gcc在预处理结束后停⽌编译过程。
- 选项“-o”是指⽬标⽂件,“.i”⽂件为已经过预处理的C原始程序。
编译(生成汇编)
- 在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的⼯作, 在检查无误后,gcc 把代码翻译成汇编语言
- 用户可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。
- 示例:gcc –S hello.i –o hello.s
- 编译过程为 扫描程序–>语法分析–>语义分析–>源代码优化–>代码生成器–>目标代码优化
- 扫描程序进行词法分析,从左向右,从上往下扫描源程序字符,识别出各个单词,确定单词类型
- 语法分析是根据语法规则,将输入的语句构建出分析树,或者语法树,也就是分析树parse tree 或者语法树 syntax tree
- 语义分析是根据上下文分析函数返回值类型是否对应这种语义检测,可以理解语法分析就是描述一个句子主宾谓是否符合规则,而语义用于检测句子的意思是否是正确的
- 目标代码生成指的是,把中间代码变换成为特定机器上的低级语言代码
汇编(生成机器可识别代码)
- 汇编阶段是把编译阶段⽣成的“.s”⽂件转成目标⽂件
- 读者在此可使⽤选项“-c”就可看到汇编代码已转化为“.o”的⼆进制目标代码了
- 示例:gcc –c hello.s –o hello.o
链接(生成可执行文件或库文件)
- 在成功编译之后,就进⼊了链接阶段
- 实例: gcc hello.o –o hello
动态链接和静态链接
- 在我们的实际开发中,不可能将所有代码放在⼀个源⽂件中,所以会出现多个源⽂件,⽽且多个源文件之间不是独⽴的,而会存在多种依赖关系,如⼀个源⽂件可能要调⽤另⼀个源文件中定义的函数, 但是每个源⽂件都是独⽴编译的,即每个*.c⽂件会形成⼀个*.o⽂件,为了满足前⾯说的依赖关系,则需要将这些源⽂件产⽣的⽬标⽂件进⾏链接,从而形成⼀个可以执行的程序。这个链接的过程就是静态链接。
- 静态链接缺点:
- 浪费空间::因为每个可执⾏程序中对所有需要的⽬标⽂件都要有⼀份副本,所以如果多个程序对 同⼀个⽬标⽂件都有依赖,如多个程序中都调⽤了printf()函数,则这多个程序中都含有 printf.o,所以同⼀个⽬标⽂件都在内存存在多个副本;
- 更新困难:因为每当库函数的代码修改了,这个时候就需要重新进⾏编译链接形成可执⾏程序。
- 优点:在可执⾏程序中已经具备了所有执⾏程序所需要的任何东西,在 执⾏的时候运⾏速度快。
- ==动态链接的基本思想是把程序按照模块拆分成各个相对独⽴部分,在程序运⾏时才将它们链接在⼀起形成⼀个完整的程序,==⽽不是像静态链接⼀样把所有程 序模块都链接成⼀个单独的可执⾏⽂件。
条件编译
- 在预处理阶段就改变代码了,有以下三个作用
- 软件按照专业度、收费情况等进行区分,使用条件编译进行代码的动态裁剪
- 内核源代码也是采用条件编译进行代码裁剪
- 开发工具,应用软件
- 让 M 存在 :gcc code.c -o code -DM
- 让 M 存在且等于100 :gcc code.c -o code -DM=100 ,相当于#define M 100 插入到我们的代码中
gcc常用选项(了解)
- -E 只激活预处理,这个不⽣成⽂件,你需要把它重定向到⼀个输出⽂件⾥⾯
- -S 编译到汇编语⾔不进⾏汇编和链接
- -c 编译到⽬标代码
- -o ⽂件输出到⽂件
- -static 此选项对⽣成的⽂件采⽤静态链接
- -g ⽣成调试信息。GNU调试器可利⽤该信息
- -shared 此选项将尽量使⽤动态库,所以⽣成⽂件⽐较⼩,但是需要系统有动态库
- -O0 / -O1 / -O2 / -O3编译器的优化选项的4个级别,-O0表⽰没有优化,-O1为缺省值,-O3优化级别最高
- -w 不⽣成任何警告信息
- -Wall ⽣成所有警告信息
库
- 我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现。
- 系统把这些函数实现都被做到名为libc.so.6的库⽂件中去了,在没有特别指定时,gcc会到系统默认的搜索路径“/usr/lib”下进⾏查找,也就是链接到libc.so.6库函数中去,这样 就能实现函数“printf”了,⽽这也就是链接的作⽤
静态库和动态库
- 静态库是指编译链接时,把库⽂件的代码全部加⼊到可执⾏⽂件中,因此⽣成的⽂件⽐较⼤,但在运行时也就不再需要库⽂件了。其后缀名⼀般为“.a
- 动态库与之相反,在编译链接时并没有把库⽂件的代码加⼊到可执⾏⽂件中,⽽是==在程序执⾏时由运⾏时链接⽂件加载库,==这样可以节省系统的开销。动态库⼀般后缀名为“.so”
- gcc在编译时默认使⽤动态库。完成了链接之后,gcc就可以⽣成可执⾏⽂件,如下所⽰。 gcc hello.o –o hello
- gcc默认⽣成的⼆进制程序,是动态链接的
- linux下
- 动态库 xxx.so ,静态库 xxx.a
- windows下
- 动态库xxx.dll,静态库 xxx.lib
- 查看可执行程序依赖的动态库,用 lld
$ ldd hello
linux-vdso.so.1 => (0x00007fffeb1ab000)
libc.so.6 => /lib64/libc.so.6 (0x00007ff776af5000)
/lib64/ld-linux-x86-64.so.2 (0x00007ff776ec3000)
# ldd 命令⽤于打印程序或者库⽂件所依赖的共享库列表
- 动静态库对比:
- 动态库形成的可执行程序体积一定很小
- 可执行程序对静态库的依赖度小,动态库不能缺失
- 程序运行需要加载到内存,使用静态链接的会在内存中出现大量重复的代码
- 动态链接比较节省内存和磁盘资源








