【Linux篇】:Linux常用工具全解析--探索高效的工具宝藏
✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨
✨ 个人主页:余辉zmh–CSDN博客
✨ 文章所属专栏:c++篇–CSDN博客
文章目录
- 一.Linux软件包管理器-yum
- yum基本命令
- 二.Linux编辑器-vim
- 1.vim命令模式常用命令
- 2.vim底行模式常用命令
- 三.Linux编译器-gcc/g++
- 1.预处理
- 2.编译
- 3.汇编
- 4.连接
- 5.补充内容
- 1.函数库
- 2.如何实现连接的
- 四.Linux项目自动化构建工具-make/makefile
- 1.自动化原理
- 2.补充内容
- 五.Linux调试器-gdb
- gdb调试器的使用
- 六.git简单命令行的使用
一.Linux软件包管理器-yum
在平常使用的电脑windows操作系统下,通常可以安装各种软来满足用户的需求,而Linux作为操作系统同样也可以安装各种软件来满足平常的工作需求。
在Linux下安装软件,一个通常的办法是下载到程序的源代码,然后编译形成可执行文件,得到可执行程序。但是这样做太麻烦,于是有些人把一些常用的软件提前编译好,做成软件包(可以理解为windows上的安装程序)放在一个服务器上,通过软件包管理器就可以很方便的获取到这个编译好的软件包,直接进行安装。
软件包和软件包管理器就好像手机中的应用市场和应用软件APP之间的关系。
而yum(全程Yellowdog Updater Modified
),就是一款Linux下的软件包管理器,可以自动处理依赖关系(在Linux操作系统中的各种软件之间可能存在各种依赖关系),支持软件包的安装,更新,删除,查询等。
yum基本命令
-
查看软件:
通过
yum list
命令可以罗列出当前操作系统下一共有哪些安装包,但是由于安装包数量过多,可以通过使用行过滤grep
来筛选出目标软件包。yum list | grep [目标软件] eg: yum list | grep gcc
(后面还有很多软件包信息,这里没有截完)。
-
安装软件:
选项
-y
可带可不带,不带会直接安装不进行询问。yum install (-y) [目标软件] eg: yum install gcc
在安装软件时,如果是在超级用户上,可以直接安装没有限制,安装后,由超级用户创建的普通用户同样可以使用对应的的安装软件。但是如果是直接在普通用户上安装,需要使用
sudo
获取对应的权限sudo yum install (-y) [目标软件]
-
删除软件:
选项
-y
同样可带可不带,不带会直接删除不进行询问。yum remove (-y) [目标软件] eg: yum remove gcc
同样,超级用户删除软件没有限制,普通用户删除软件需要获取对应的权限
sudo yum remove (-y) [目标软件]
补充一个知识点:sudo对一条命令提取权限
当普通用户对一条命令提取权限时,如果没有在系统对应的白名单中是无法提取权限的,会发出警告:
因此普通用户使用sudo指令时,需要先在对应的白名单中加入普通用户名。
使用超级用户查看对应的白名单etc/sudoers
:
在/etc/sudoers
文件第一百行中可以看到白名单中的用户信息,将要添加的用户添加到后面即可(这里需要使用vim编辑,后面会讲到)。
二.Linux编辑器-vim
vim是一款Linux下的编辑器,可以用来文本编写,也就是写代码,vim是一个多模式的编辑器,每个模式下都有对应的功能以及操作,这里重点讲解三种模式:命令模式,插入模式,底行模式。
通过输入指令即可进入对应的编辑:
vim [目标文件]
-
命令模式(Normal mode):
通过指令进入编辑后,默认就是命令模式,该模式是控制屏幕光标的移动;字符,行或者块的删除,复制,拷贝等等,在当前模式下用户所有的输入都会被当作命令,一般不会作为文本输入。
-
插入模式(Insert mode):
只有在插入模式下,才可以进行文本输入,如果要退出当前模式,按
ESC
即可,推出后会回到命令模式。从命令模式切换到插入模式需要按i
键。 -
底行模式(Last line mode):
用于文件的保存或者推出,也可以进行文件替换,找目标字符串,列出行号等等。如果要退出当前模式,还是按
ESC
即可,推出后会回到命令模式。从命令模式再切换到底行模式需要按shift+;
键,其实就是:
键。
上面三种模式只是最常用到的模式,并不是只有这三种模式。根据上面的讲解,可以知道命令模式是默认模式,同时也是基本模式,从命令模式可以切换到其他模式,其他模式退出后会回到命令模式。
1.vim命令模式常用命令
- 移动光标:
按[gg]:
定位光标到最开始行
按[shift+g](G):
定位光标到结尾行
按[n(指定行号)+shift+g](n+G):
定位光标到任意行
按[shift+$]:
定位光标到当前行结尾
按[shift+^]:
定位光标到当前行开始
按[w]:
光标跳转到下一个字的开头
按[b]:
光标跳转到上一个字的开头
按[e]:
光标跳转到下一个字的结尾
按[h/j/k/l]:
光标上下左右移动
- 复制粘贴:
按[(n) yy]:
复制光标所在行或者n行
按[(n) p]:
粘贴(n行)到当前光标所在行的下一行
- 删除剪切:
按[(n) x]:
对光标之后的字符或者n个字符进行删除
按[(n) dd]:
删除并拷贝当前光标所在行或者n行,如果删除拷贝后在其他行粘贴就是剪切操作,如果删除拷贝后没有粘贴就是删除操作
- 替换:
按[shift+~]:
对光标字符进行大小写转换
按[(n) r]:
对光标字符或者n个字符进行批量化替换
按[shift+r](R):
进入替换模式,对内容进行整体替换
- 撤销:
按[u]:
撤销上一个操作
按[ctrl+r]:
撤销之前的撤销
2.vim底行模式常用命令
- 列出和去掉行号:
调出行号:
set nu
去掉行号:
set nonu
- 保存文件:
将当前文件中的内容保存:
w
强制保存:
w!
- 退出vim:
直接退出vim:
q
保存并退出:
wq
强制退出:
q!
强制保存并推出:
wq!
- 查找字符:
先按[/]键,然后输入要查找的字符,如果第一次找到的不是想要的关键字,可以一直按[n],会往后寻找,知道找到想要的关键字为止:
/+关键字
先按[?]键,然后输入要查找的字符,如果第一次找到的不是想要的关键字,可以一直按[n],会往前寻找,知道找到想要的关键字为止:
?+关键字
三.Linux编译器-gcc/g++
gcc编译器是用于C语言文件的编译,而g++则是用于C++文件的编译,这两个的使用方法完全相同,学会一个另一个就会使用,这里以gcc为例:
gcc指令格式:
gcc [选项] [要编译的文件] [选项] [目标文件]
编译文件形成可执行文件并不是一次性的直接形成,而是经过四个阶段预处理,编译,汇编,连接,才最终形成了可执行文件。
1.预处理
-
功能:
预处理阶段主要功能包括进行宏替换,头文件展开,去掉注释,条件编译等。
-
指令:
gcc -E [要预处理的文件:xxx.c] -o [形成的目标文件:xxx.i]
-
选项作用:
[-E]选项的作用是让gcc从现在开始进行程序的翻译,在预处理工作完成后就停止编译过程;[-o]选项是指生成目标[.i]文件,[.i]文件为已经经过预处理阶段的原始程序。
-
示例:
图片左边为要编译的.c文件,右边为已经完成预处理阶段的.i文件,右边文件中的行数在经过头文件展开后变成了八百多行,红色方框中的注释也已经去掉,绿色方框中的宏也已经完成替换
这里补充一下关于头文件的知识:为什么能够在windows或者Linux操作系统上进行C或者C++或者其他形式的开发呢?
这是因为我们的系统中一定要提前或者后续安装上,C/C++开发相关的头文件和库文件。C/C++开发环境不仅仅指的是vs,gcc,g++等编译工具,更重要的是,语言本身的头文件和库文件!
其实之前在安装vs2019或者vs2022的时候,选择对应的开发包,同时也在下载对应的头文件和库文件,编译型语言安装开发包,必定是下载安装对应的头文件和库文件。
2.编译
-
功能:
在编译阶段,gcc首先要检查代码的规范性,是否有语法错误等,如果出现错误,就会报出编译错误。在检查无误后,gcc就会把代码翻译成汇编语言。
-
指令:
要编译的文件可以是xxx.c,也可以是xxx.i gcc -S [要编译的文件:xxx] -o [目标文件:xxx.s]
-
选项作用:
[-S]选项的作用是让gcc在编译阶段完成后停止整个编译过程,具体要编译文件可以是[.c]或者[.i]文件;[-o]选项的作用是指生成目标文件[.s],[.s]文件是已经完成预处理和编译两个阶段的文件。
-
示例:
3.汇编
-
功能:
汇编阶段是将编译阶段生成的[.s]文件转化为机器可以识别的代码
-
指令:
要汇编的文件可以是xxx.c文件也可以是xxx.i文件也可以是xxx.s文件 gcc -c [要汇编的文件:xxx] -o [目标文件:xxx.o]
-
选项作用:
[-c]选项的作用是让gcc在汇编阶段完成后停止整个编译过程,具体要汇编文件可以是[.c]或者[.i]文件或者[.s]文件;[-o]选项的作用是指生成目标文件[.o],[.o]文件是已经完成预处理,编译以及汇编三个阶段的文件。
-
示例:
4.连接
-
功能:
将汇编文件与库文件进行连接生成可执行文件
-
指令:
要连接的文件可以是xxx.c,也可以是xxx.i,也可以是xxx.s,也可以是xxx.o文件 gcc [要连接的文件:xxx] -o [目标文件:xxx]
-
选项作用:
因为连接是四个阶段的最后一个阶段,所以不需要类似于[-E]和[-S]等选项;[-o]选项的作用是指生成目标文件,该文件是已经完成四个阶段的可执行文件。
-
示例:
5.补充内容
1.函数库
前面讲到整个编译过程分为四个阶段,其中最后一个阶段为连接阶段,如何理解连接?
以C语言中的printf
函数为例,在使用该函数时,并没有定义该函数的实现,且在预编译中包含的头文件stdio.h
中也只有该函数的声明,而没有实现,那么是在哪里实现printf
函数的?
答案是:系统把这些函数实现都存放到名为libc.so.6
的库文件中,在没有特别指定时,gcc会到系统默认的搜索路径/usr/lib
下进行查找,也就是连接到libc.so.6
库函数中去,这样就能实现函数printf
了,这也就是连接的作用。
而函数库分为两种,一种为动态库,一种为静态库
在Linux中.so
为动态库,.a
为静态库;而在windows中.dll
为动态库,.lib
为静态库。
在我么自己的机器上,默认只会安装动态库,静态库默认是没有安装的。
安装静态库:
C语言的静态库安装:
sudo yum install -y glibc-static
C++的静态库安装:
sudo yum install -y libstdc++-static
各种函数的实现就在库中!通过库可以不用做重复工作!
库其实就是把.c
源文件经过一定的翻译,然后打包,只提供一个文件即可,不用提供太多的源文件,也可以达到隐藏源文件的目的。
头文件提供方法的声明+库文件提供方法的实现+代码=完整的软件
查看动态库:
2.如何实现连接的
连接阶段作为编译的最后一个阶段,将.o
文件和库进行连接,形成可执行程序,但是如何实现连接的?
现阶段只需了解连接的原理即可,后面学到其他的会更深层次的讲解。
-
动态连接:
当可执行程序执行到某处需要调用该函数的实现时,会自动跳转到对应的动态库中执行,当执行完后又返回到代码的调用处,继续执行下一行代码。
如果其他可执行文件调用该函数时,同样可以跳转到对应的动态库中执行,所以动态库又叫做共享库。
因此动态库不能缺失,一旦对应的动态库缺失,影响的不止一个程序,可能导致很多程序都无法进行正常运行。
查看可执行文件所需的动态库:
-
静态连接:
在编译器使用静态库进行静态连接的时候,会将自己的方法拷贝到目标文件中,该程序以后不用再依赖静态库。但是生成的文件会比较大。
验证:
在Linux中,编译形成的可执行程序,默认采用的就是动态连接(提供动态库),而如果要按照静态连接的方式形成可执行程序,需要添加-static
选项(提供静态库)。
注意点:
如果没有静态库,但是就是要进行静态连接是不行的;如果没有动态库,只有静态库而且gcc能找到对应的静态库,编译连接时就会使用静态连接。
因此gcc默认使用动态库进行动态连接,-static
的本质就是改变优先级。
动静态连接的优缺点:
动态库因为是共享库,有效的节省资源(磁盘空间,内存空间,网络空间等)这是优点;但是一旦动态库缺失,导致各个程序都会无法执行这是缺点。
静态库不依赖函数库,程序可以独立运行这时优点;但是体积大,比较消耗资源,这是缺点。
四.Linux项目自动化构建工具-make/makefile
先阶段因为只是写一些单个文件的简单代码,所以可以直接使用gcc/g++对该文件进行编译,但是如果放在整个项目中,一个一个编译就会比较麻烦,这时候就需要用到自动化构造工具-make和makefile,其中make是一条命令,makefile是一个文件。
一个工程项目的源文件不计其数,按照类型,功能,模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先进行编译,那些文件需要后进行编译,那些文件需要重新进行编译,甚至于进行更复杂的功能操作。
两个搭配使用,就可以完成项目自动化构建。
1.自动化原理
在makefile文件中,需要定义对应的规则才能实现自动化构建,需要依赖关系和依赖方法来实现,两个缺一不可。
以text.c文件编译形成text可执行文件为例
makefile文件中:
text:text.c ---依赖关系
gcc text.c -o text ---依赖方法
在依赖关系中,冒号:
左侧为目标形成的可执行文件;右侧为形成可执行文件依赖的源文件。
在依赖方法中,前面的空白处并不是空格跳过,而是使用TAB
键跳过,然后按照源文件如何形成目标文件写入对应的指令,这就是依赖方法。
根据makefile中的依赖关系和依赖方法,就可以通过make指令直接完成编译。
编译形成可执行文件有了,但是如果想要删除该文件呢?同样可以在makefile文件中通过依赖关系和依赖方法来实现
makefile文件中:
text:text.c ---依赖关系
gcc text.c -o text ---依赖方法
clean: ---依赖关系
rm -f text ---依赖方法
在删除的依赖关系中,冒号左侧的clean依赖的右侧为空,而依赖方法中则是删除该文件的指令。
2.补充内容
1.make会自动推导makefile文件中的依赖关系
如果将编译分为完整的四个阶段,用四个依赖关系来实现源文件形成可执行文件,如图所示:
使用make指令时,根据makefile文件中的依赖关系从下到上依次执行,有点类似于递归调用,栈式结构。
2.makefile文件中的第一个依赖关系会作为默认的make指令
比如将删除的依赖关系作为第一个,使用make指令时,就会用到删除的依赖方法。
通常将编译的依赖关系设置为第一个,作为默认make指令。
3.如何实现makefile文件中的依赖关系总是被执行(伪目标)
make指令在编译一次后,生成可执行程序,如果源文件中没有更改,再次执行编译的make指令将不再执行。
为什么要这样限制?答案是提高编译效率。现在自己写的也就是一些比较简单的几行或者几百行代码,编译一次很快就能完成;但如果是在很大的项目中进行编译,编译一次就会花费很长的时间,所以如果源文件没有更改的话,就没有必要再编译一次,可以提高编译的效率。
但又是怎么做到的可以判断当前源文件是否更改过?因为一定是由源文件形成可执行文件,也就是先有的源文件后有的可执行文件,因此源文件的最近修改时间一定比可执行文件的最近修改时间要早。如果更改了源文件,历史上曾经还有可执行文件,那么源文件的最近修改时间一定要比可执行文件的要晚。
只需比较可执行文件和源文件的最近修改时间就能判断出是否需要进行再次编译
可执行文件的最近修改时间 晚于 源文件的最近修改时间,不需要重新编译
可执行文件的最近修改时间 早于 源文件的最近修改时间,需要重新编译
一般而言不会有可执行文件的最近修改时间等于源文件的最近修改时间
一个文件有三种时间,分别是最近访问时间(Access
),最近更改文件内容的时间(Modify
),最近更改文件属性的时间(Change
),可以通过指令stat [目标文件]
来查看目标文件的三个时间。
make会根据源文件和目标文件的新旧(Modify
时间),判断是否需要重新执行依赖关系进行编译!
因此依赖关系并不一定总是执行的!如果想让对应的依赖关系总是被执行,可以使用.PHONY:
伪目标。
通常将清理文件的依赖关系设置为伪目标
完整的makefile写法:
在编译文件的依赖方法中,红色方框中的$@
表示的依赖关系中冒号左侧的可执行文件,$^
表示依赖关系中冒号右侧的源文件;在依赖方法中的指令语句前还有一个@
用来隐藏make指令执行依赖关系时的依赖方法。
五.Linux调试器-gdb
程序发布时有两种方式:debug模式和release模式。其中debug模式能被调试,因为形成可执行程序的时候会有调试信息;而release模式则不能调试,因为没有调试信息。所以debug模式的可执行程序的大小要比release模式的可执行程序的大小大。
另一点Linux下的编译器gcc和g++都是默认以release模式发布的,如果要以debug模式发布,在使用编译指令时,要携带[-g]选项。
使用指令readelf -S [目标文件] | grep -i debug
可以查看目标文件的调试信息。
gdb调试器的使用
启动调试:
gdb [调试的目标文件]
查看目标文件中的代码:
查看部分文件中的代码:
list(可以简写为l)
查看前十行的代码(执行一次后再次执行,会接着上次的位置往下列,每次十行:
l + 0
补充一个:
使用回车按键,会继续使用上一条指令,因此如果想要查看完整的代码,可以在使用l + 0后一直回车
查看指定函数中的代码
l + 函数名
执行代码:
r
断点:
设置断点
b + [指定行号]
补充:设置的断点在代码中看不到,只能通过指令看到
查看断点
info b
删除断点需要用到断点前面的编号,根据编号删除而不是行号
d + [断点编号]
执行语句:
逐过程调试(相当于vs 2022调试中的f10按键)
n
逐语句调试(相当于vs 2022调试中的f11按键)
s
变量:
查看当前变量的值:
p + [变量名]
使用p时,每次逐过程执行语句时,当前查看的变量并不会发生变化,如果要像监视窗口中的变量一样,每次都会发生变化
可以使用display +变量名,其中变量前面的编号用于删除
删除变量:
undisplay +编号
从循环中跳出执行:
until + [要跳转到的行数]
使用s跳转到另一个函数时想要直接退出该函数:
finish
从当前断点到另一个断点:
c
使指定断点禁用:
disable + [断点编号]
使指定断点工作:
enable + [断点编号]
六.git简单命令行的使用
Git
是一个开源的分布式版本控制系统,用于高效的管理项目(尤其是代码)的版本和变更记录。git其实和Linux还是有联系的,因为最初的git就是用于管理Linux内核的开发。
Git的生态非常强大,与gitee(国内的),github(国外的)等平台无缝集成,成为开发这协作的行业标准。
这里主要简单讲解一下如何在Linux操作系统下将自己写的代码上传到自己的git代码库中,会用即可,后面会专门讲解git的使用。
以国内的gitee为例:
先在gitee上创建代码库
输入需要创建的仓库名称,下面的各种选项根据自己的需求选择,可选可不选,选择好后点击下面的创建即可。
创建好后,就可以看到创建的仓库,点击右上角的克隆/下载
获取当前仓库的链接
获取到链接后,在Linux操作系统下进行操作:
先克隆到本地仓库,就可以在当前操作系统下看到以目录形式创建好的仓库
git clone [链接]
如何上传代码文件:
如果是第一次使用git需要先配置用户名和邮箱,以确保提交代码的身份被gitee正确识别
git config --global user.name '[用户名]'
git config --global user.email '[邮箱]'
配置好后就可以使用了。
第一步:
将需要上传,用git管理的文件告知git
git add [目标文件名]
第二步:
提交改动到本地
git commit . -m [日志内容]
.表示当前目录
提交的时候可以用[-m]选项,注明提交日志(最好注明)
第三步:
同步到远端服务器上
git push
需要先填入用户名和密码(这里的密码是登录gitee网站时的密码),同步成功后,刷新gitee页面就能看到上传的代码文件。
如果需要删除仓库,点击管理,然后找到删除仓库的选项,根据指示操作,就可以删除仓库了。
以上就是关于Linux常用工具的讲解,如果哪里有错的话,可以在评论区指正,也欢迎大家一起讨论学习,如果对你的学习有帮助的话,点点赞关注支持一下吧!!!