Linux开发工具
- 前言
- Linux编辑器 --- vim
- vim长啥样
- vim的基本概念
- vim的配置
- Linux编译器 --- gcc/g++
- 编译和链接
- 预处理
- 编译
- 汇编
- 链接
- 细🔒链接
- 静态库和动态库
- Linux调试器 --- gdb
- Linux项目自动化构建工具 --- make/Makefile
- 依赖关系和依赖方法
- 上方工具的简单示例
前言
对于像我这样的新手来说,刚从windows下换到linux下真心有些不适应,但是学linux毕竟是重中之重的事情,像我一样刚接触的同学就不要抱怨那么多了,好好学,想想你刚接触C语言的时候是啥样的,慢慢适应就行。
Linux编辑器 — vim
相信不少同学还沉浸在非常方便的vs2019这种集成开发环境中。
但是如果下面的这些学好了,可能用起来比 vs 等等的集成开发环境还要方便,虽然我不知道是真是假,但是很多大佬都是这样说的,等你学好了成为大佬了也可以这样说。
首先可以看到目录标题的 “ 编辑器 ” ,编辑器其实没什么,如果光是写东西的话,那就跟记事本没什么两样,但是vim是一款多模式编辑器。还有vim的前身vi也是。
看图:
vi/vim的区别简单点来说,它们都是多模式编辑器,不同的是vim是vi的升级版本,它不仅兼容vi的所有指令,而且还有一些新的特性在里面。例如语法加亮,可视化操作不仅可以在终端运行,也可以运行于x window、 mac os、windows。
vim长啥样
在命令行中,使用对一个文件进行编辑的命令:vim 文件名。
下面我创建了一个test.c文件:
如果你没有对vim进行过任何配置的话,屏幕就变成了这样:
然后你会发现按什么东西都没用,先别急胡乱按。
先退出:shift + ;(也就是:),然后再按下q,再按回车,就可以退出去了。
如果你左下角有这个东西:
说明你肯定乱按了,也别急,按下esc,就是你退出游戏常按的那个,然后再shift + ;(也就是:),然后再按下q,再按回车,就可以退出去了。
可能你之前看过别人的vim跟你刚刚打开的不一样,就是因为你还没有配置vim,但是如果你对vim配置过的话可能就是我这样的:
怎么配置的话先不要着急,我会在最后的时候讲到,目前我就用还没有配置过的那种。
好,你已经看到了vim长啥样了,也看到了刚刚最后一个图片下面的INSERT,那就先讲这个INSERT。
vim的基本概念
前面也说了vim是一个多模式编辑器,就讲vim的三种模式(其实有好多模式,目前掌握这3种即可),分别是命令模式(command mode)、插入模式(Insert mode)和底行模式(last line mode),各模式的功能区分如下:
正常/普通/命令模式(Normal mode)这个是刚进入vim的模式
控制屏幕光标的移动,字符、字或行的删除,移动复制某区段及进入Insert mode下,或者到 last line mode
插入模式(Insert mode) 这个就是刚刚左下角出现INSERT时候的模式
只有在Insert mode下,才可以做文字输入,按「ESC」键可回到命令行模式。该模式是我们后面用的最频繁的编辑模式。
末行模式(last line mode)这个是按了 :(shift + ;)后的模式
文件保存或退出,也可以进行文件替换,找字符串,列出行号等操作。 在命令模式下,shift+;即可进入该模式。要查看你的所有模式:打开vim,底行模式直接输入:help vim-modes
这些模式有啥用?
先别急,先看下怎么互相切换:
那么命令模式退出就是 : q了。
现在再说有什么用。
先说插入模式:
这个模式里就相当于在里面编写代码了,进入插入模式记得按 i 或者 a 或者 o (还有别的,但是这三个对于小白来说已经够了,甚至光记住 i 就行)。
给个简单的例子:
写好之后怎么保存呢,直接回到命令模式下,然后在退出命令模式之前:w。这就是保存,然后退出就行,当然也可以:wq来直接保存并推出命令模式。如果你保存或者退出的时候下面提示了一堆红色信息,不要管,直接:w!或者:q!(记得退出前保存)或者:wq!就可以强制退出。
再说命令模式:
命令模式下有很多的快捷键,记起来的话很多,下面的这些先过个眼瘾,不建议硬背,记不住没关系,多练就行,下面的操作不方便演示,大家可以按着操作挨个试试,我就不给图片演示了。
快捷键:
光标类的:
vim可以直接用键盘上的光标来上下左右移动,但正规的vim是用小写英文字母「h」、「j」、「k」、「l」,分别控制光标左、下、上、右移一格(也可以用上下左右键,但是不推荐,还是用hjkl好,多适应就行。)
按「G(shift + g)」:移动到文章的最后
按「 $ 」:移动到光标所在行的“行尾”
按「^」:移动到光标所在行的“行首”
按「w」:光标跳到下个字的开头
按「b」:光标回到上个字的开头
按[gg]:进入到文本开始
按[shift+g]:进入文本末端
新手的话,这些已经够多了,把这些先记住就行,还有一些就不介绍了。文本操作类的
删除文字:
「x」:每按一次,删除光标所在位置的一个字符
「#x」:例如,「6x」表示删除光标所在位置的“后面(包含自己在内)”6个字符
「X」:大写的X,每按一次,删除光标所在位置的“前面”一个字符
「#X」:例如,「20X」表示删除光标所在位置的“前面”20个字符
「dd」:删除光标所在行
「#dd」:从光标所在行开始删除#行复制:
「yy」:复制光标所在行到缓冲区。
「#yy」:例如,「6yy」表示拷贝从光标所在的该行“往下数”6行文字。
「p」:将缓冲区内的字符贴到光标所在位置。注意:所有与“y”有关的复制命令都必须与“p”配合才能完成复制与粘贴功能。
如果是 dd 了之后再换光标的位置,再p就是剪切的功能。
「#p」:一次粘贴#行「u」:如果您误执行一个命令,可以马上按下「u」,回到上一个操作。按多次“u”可以执行多次回复。
「ctrl + r」: 撤销的恢复
底行模式
就说几个简单的
进入了底行模式后
[set nu],可以将行号调出来;[set nonu]可以将行号隐藏
[vs 文件名]可以多文件编辑,
ctrl + w + w 可以文件之间切换光标,光标所在位置就是你当前编辑的位置
如果是多文件退出的时候是用q退出(退出记得保存)当前编辑的文件,就会关闭编辑文件,然后就剩下其他的文件了。
底行模式就说这么些。
vim的配置
下面就说怎么来配置vim。配置前先看一下我的配置:
长这样:
但是要说一点,每个人的配置可能都不一样,我是这样的,但是别人可能就不是这样,配置的样子取决于你的需求,但是一般不需要那么复杂的配置。
首先声明两点:
- 配置vim的时候非常不建议用root用户来配置。
- 不同的用户所配置的vim是互不影响的,比如说root和普通用户,普通用户配置了vim,不会影响root用户的vim配置。或者一个普通用户A配置了vim,但普通用户B没有配置vim,那么A在使用vim的时候就可能和我上面的黑色背景的vim一样,但是B就是我最开始为你们展示的那种没有配置过的vim。
先说基本的方法:创建 .vimrc (不建议)。
首先切换到你的家目录下:
如果家目录下没有 .vimrc 就创建一个
然后对这个文件编辑 vim .vimrc 就行
就举一个例子:进去之后输入 set nu,这是我上面说过的底行模式中的命令,就是显示行号。
输入好之后保存并退出,下次vim编辑文件的时候就可以自动显示行号了。
ok,上面也说了不建议用上面的方法来配置vim,因为还要搜索,太麻烦了,下面我直接给我的vim的配置命令(其实我也是在网上搜的),你们只要复制下面这条指令再拷贝到命令行上,一个回车,需要按照提示输入 root 密码.,您的 root 密码不会被上传, 请放心输入。输入了之后就可以跟我的vim配置的一样了。
注意下面的vim配置只支持Centos 7。
curl -sLf https://gitee.com/HGtz2222/VimForCpp/raw/master/install.sh -o ./install.sh && bash ./install.sh
这里安装配置的时候比较慢,多等一会,我当时安装的时候就很慢。
安好了之后最下面一行会有这样的一句话:
安装成功!请手动执行 “source ~/.bashrc” 或者重启终端,使 vim 配置生效。
看见了之后不要慌,照着输入 source ~/.bashrc 这条命令就行。
我就是这样配置vim的,大家不要害怕上当什么的。
配置好了之后在进入vim就变成这样了:
Linux编译器 — gcc/g++
其实gcc我已经在前面的博客中讲过了,想看细节的话点这个:看程序环境就行
下面我就粗略的过一遍。
“翻译” 一个 .c 文件会默认生成一个a.out,其实a.out就相当于Windows里的.exe可执行文件。
根据我们刚刚编辑好的test.c文件,我们可以对它 “翻译” 一下,这个过程其实就是编译和链接。
怎么做?
下面这样:
gcc 文件名
这样就生成了一个可执行文件。
那这个文件怎么执行?
下面这样:
./ 文件名
注意一定要加 ./ 不然是错误的,./xxx代表的是执行当前目录中的xxx文件。
编译和链接
看了我刚给的那篇博客的话,应该就知道了编译还可分为预处理、编译、汇编。下来才是链接,我就过大概过一遍。然后把图解给出来就行。
初始的 .c 文件内容
预处理
gcc -E test.c -o test.i
这条命令是把预处理做完就停,-o 选项是将生成的文件命名为 test.i
test.i中的内容(很多,没法全部展示)
编译
gcc -S test.i -o test.c
这条命令是完成编译就停,-o 跟上面一个意思
test.s中的内容(都是一些汇编指令)
汇编
gcc -c test.s -o test.o
汇编形成二进制文件,还不能执行,需要和其它文件进行链接。
test.o中的内容(根本就不认识)
链接
gcc test.o -o test
生成可执行文件test,如果没有-o,默认情况就是a.out
现在就能执行了
上面的过程很繁琐,不需要每次生成可执行文件的时候都要挨个搞,直接gcc就行:
上面的就是翻译的基本操作。
然后我们下面细🔒一下链接:
细🔒链接
首先,语言是有库的,一套头文件 + 一套库文件(linux下:libc.a (静态库), libc.so(动态库))
需要链接来将我们字节的代码中的函数调用,外部数据和库关联起来。
ldd 文件名
就可以看到文件链接的第三方库
例子:
可以看到是动态库
那静态库和动态库有啥区别?
静态库和动态库
首先先看张图:
静态库和动态库都和程序成功运行有关。
大家可能对Windows下的库的后缀比较熟,.lib 是我们之前用vs类的IDE经常见的文件,我觉得.dll 文件主要是在各位打游戏的时候游戏打不开了,蹦出来一个窗口说你的什么什么.dll 文件丢失啥的,这个时候.dll 文件就见过了。
然后Linux的静态库以.a为后缀,动态库以.so为后缀。
gcc test.c -o test
这条命令中,要注意的是gcc默认采用动态链接方式,形成可执行程序。
若想静态链接方式,则手动添加 -static,像下面这样
gcc test.c -o test_static -static
若执行了上面的代码后出现了 not found lc,则用yum安装静态库就行。
然后就能得到一个静态链接的文件
但是静态链接会将库中的代码拷贝到文件中,所以会导致最终文件大小比动态链接所形成的文件要大。
也是可以执行的:
也可以看其的库是动态还是静态的:
gcc讲得差不多了,再说下g++。
g++其实就是用在C++文件上的,gcc是用在C语言上的,但是C++是兼容C的,g++也可以用在C语言上,看图:
这里就再写一个C++文件,用g++编译一下,剩下的那些细节就跟gcc是一样的,不再展开讲了。
上面默认生成了 a.out 文件
最后要说一点就是Linux下各种语言都是能跑的,不像Windows下跑不同的语言要换不同的软件来跑。但迫于我能力有限,就没法给大家展示跑Java、python等语言了。。。
Linux调试器 — gdb
说到调试器,大家肯定能想到在vs上调试的时候有各种快捷的按键,Linux下也可以调试,也有一些快捷键, 但是要说一点,Linux下用gdb调试会非常的麻烦,个人感觉还是vs下的调试比较爽,用gdb是真的比较恶心。不说那么多了,开整:
首先,大家都知道可执行程序如果是release版本的话是不能调试的。必须是debug版本才能调试的。
如何查看一个程序是debug还是release的呢?
readelf -S 文件名
这条命令可以看到可执行程序的段构成(先不管是什么意思,以后博客中会说的)
再加个管道:
readelf -S 文件名 | grep debug
这样就能查看是否是debug版本了
当什么都没有输出的时候就是release版本的。因为如果一个程序是可调式的,该程序的二进制文件中一定加入了一些debug信息。
centos中,默认的可执行程序是release版本的,release版本下没有假如debug信息,所以debug版本的体积要更大一些。
如要使程序变成debug版本,给 gcc/g++ 添加 -g 选项就可以了。
这样就行。
我觉得调试的时候最重要的几点就是打断点、逐语句、逐过程、显示变量信息、跳到下一个断点,这几个功能对应到vs2019中就是F9、F11、F10、监视窗口、F5了。
该交代的都交代了。
然后就开始调试:
就是实现两个数之和
先看下文件中的内容:
gdb 文件 就是开始调试这个文件
quit 退出gdb,第一个说退出,只因这个gdb太难用了。
r / run 相当于vs2019中的 ctrl + F5
l / list 显示代码
这里不会一下将全部代码加载出来,想再看的话就再按下l
如果你想显示指定行的代码 l + 行数(函数名也可),会将所在行的前后都显示,然后再按l就是续着的
b / breakpoint + 行号,在指定行号(函数名也可)打断点,对改行打断点后并对该断点排序
如果跟函数名的话,会将断点打在函数内的第一条语句那一行。
打了断点之后再按r就会停在断点处,跑到下一个断点就不能再按r了,应该是c,这个等会讲。
info b 可以显示所有断点信息
already是说该断点已经命中过一次了,也就程序已经跑过这个断点了。就是我刚刚 r/run 了一下。
可以看到我上面两个断点重复了,可以删除一个
d + 断点编号 删除该编号的断点,不能写成 d + 行号,这不是。
s / step 逐语句(相当于vs 中的 F11)
n / next 逐过程(相当于vs中的F10)
display 变量名 (相当于vs 的监视窗口)(下面我重跑了一次,还加了个断点,从main中的a = 10 开始),会给展示的变量排序
undisplay 变量前的序号,删除该号的变量
p 变量名,展示一次变量
c / continue 直接到达下一个断点
finish 进入某个函数后,直接将该函数跑完,会显示该函数的返回值。
until 行数,直接跳转到指定行,如果中间有断点,会在断点处停下来
disable 断点序号 ,使该断点无效(就是该断点虽然存在,但是不能用,就跟没有这个断点一样)
enable 断点序号, 使该断点有效
bt 调用堆栈,堆栈不知道是啥的话我只能说百度一下。
set var 变量 = 数值 ,这个可以在调试中修改数值
好了,这些已经够多了,我是不想再用了,gdb调试用起来非常恶心,主要是不好观察,每次都是一点一点往出蹦,太难用了。
上面的指令尽量记住,如果你在简历中写了了解过gdb的话,可能面试官会问你gdb断点怎么打,你别到时候支支吾吾说不上来就行。
Linux项目自动化构建工具 — make/Makefile
make是一条指令,makefile是一个文件
二者合作,可达到多文件形成可执行程序的目的
还要说一下依赖关系和依赖方法,但是没有例子不好讲。
我就直接说例子了:
首先你要创建一个文件,文件名是makefile/Makefile,大小写由你来决定。
然后编辑这个文件,在里面写编译的东西:
依赖关系和依赖方法
然后我们执行make命令,就执行了gcc test.c -o test
就生成了一个test文件。
还可以用make test来实现和make一样的功能
上面的过程对应到vs中就相当于生成解决方案。
还可以清理解决方案,再改一下makefile:
怎么用clean:
这样无论如何都没什么问题,但是make就不行。
当我们也为test加上.PHONY时。
不会报那个问题了,但是多次同时编译,test.c不变,test还是那个test,没必要加。
还要注意一点就是make扫描makefile文件的时候,默认只会形成一个目标依赖关系,一般是第一个,若我们把刚刚的clean和test换一下位置,make就变成了clean操作,想要再用gcc test.c -o test的话就得make test。
看:
上面的是刚入门的时候写的,下面的就是以后大部分情况下写的Makefile:
当我们执行make命令的时候,会自动将test替换为 $@ ,将 test.c 自动替换为 $^
这个就讲这么多。
上方工具的简单示例
写个小进度条看看:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define NUM 100
int main()
{
char bar[NUM + 1];
memset(bar, '\0', sizeof(bar));
const char* tmp = "|\\/-";
int i = 0;
while(i <= 100)
{
printf("[%-100s][%3d%%][%c]\r", bar, i, tmp[i % 4]);
fflush(stdout);
usleep(40000);
bar[i] = '=';
bar[i + 1] = '>';
i++;
}
printf("\n");
return 0;
}
搞出来就是这样:
这里面有些关于缓冲区的东西,现在讲不太合适,以后再讲。
到此结束。。。