目录
- Linux工具的使用-03
- 1.git
- 1.1git是什么
- 1.2git在linux下的操作
- 1.2.1创建git仓库
- 1.2.2 .gitignore
- 1.2.3 .git(本地仓库)
- 1.2.4 add (添加)
- 1.2.5 commit(提交)
- 1.2.6push(推送)
- 对两个特殊情况的处理
- 配置免密码push
- 1.2.7 log(获取提交记录)
- 1.2.8 status(获取仓库状态)
- 1.2.9 mv(修改已在仓库的文件名)
- 1.2.10 rm(删除已经在仓库的文件)
- 1.2.11 pull(拉取远程仓库来同步本地仓库)
- 2.Linux调试器—gdb
- 2.1gdb的使用
- 2.2gdb的使用案例
- 拓展:readelf -S
- 2.2.1显示源代码
- 2.2.2打断点(VS的F9)
- 2.2.3删除断点
- 2.2.4开始调试(VS的F5)
- 2.2.4.1跳到下个断点
- 2.2.5逐过程(VS的F10)
- 2.2.6逐语句(VS的F11)
- 2.2.7查看调用堆栈
- 2.2.7.1将当前堆栈运行完毕
- 2.2.8监视变量(显示变量)
- 2.2.8.1p(监视单次变量)
- 2.2.8.2display(常显示变量)
- 2.2.9跳出循环
- 2.2.10查看局部变量
- 2.2.11禁用断点
- 2.2.12启用断点
- 2.3gdb的总结
Linux工具的使用-03
1.git
1.1git是什么
git简单来说就是一个版本控制器。【去中心分布式版本控制器】
它会对我们的代码的历史所有版本做一个备份一样的工作。
当然git不止这个功能,它还能做到**【多分支管理】【历史版本回退】**等功能。
但是现在的我只能用到备份这个功能。
git是开源的。因此有很多人都在使用,这其中就有些人对git进行了商业化包装,github就出现了
github在国外获得了成功之后,国内访问github访问速度不理想,因此国内工程师也开发了一个gitee出来
1.2git在linux下的操作
下面所有的操作都得建立在linux系统中下载了git的yum源
yum install git
输入上面的指令可以下载,普通用户下载要加sudo
1.2.1创建git仓库
首先创建一个仓库
在gitee或者github上面创建都是可以的
然后就将指令git clone 仓库地址
打到Linux终端运行
敲完指令后就需要验证,输入gitee的账号和密码
注意这里的账号密码
成功之后,当前目录下就会出现一个仓库
仓库里面的文件和在gitee上看到的文件是一致的,因为仓库本质就是一个目录(文件)
1.2.2 .gitignore
.gitgnore
这是一个文件,在这个文件里面的内容出现的后缀,都不会被添加到仓库中。
目的:保持远程仓库gitee不要那么乱,不然一个项目很多乱七八糟的文件都会被一起上传进去,以后找起来很麻烦
这里默认会有一些无法提交的后缀,还可以自己补充后缀,用vim修改即可
查看仓库状态【这里用到了status,后面有说】
上面我们添加了一个以.sln后缀的文件是无法被提交到远程仓库的
然后要提交commit
再push
查看远程仓库的.gitignore文件,查看是否push成功
可以看到更新成功
1.2.3 .git(本地仓库)
在linux仓库的目录下有一个.git目录。
tree
一下
.git其实就是本地仓库
git仓库本质就是就是一个目录。这个目录里面包含.git目录 + 里面的内容(代码文件和其他文件)
push到远端其实就是将本地的.git目录的内容同步到gitee上的.git目录【gitee的.git目录是不显示的】
1.2.4 add (添加)
在git仓库中添加了一个项目(实现进度条)
此时如何做到上传代码到本地仓库,然后再push到gitee的远程仓库上呢?
先要用add操作
git add .
此时myproc就被添加到了.git目录中的一个临时区域。还没有commit,不会合并到.git中
1.2.5 commit(提交)
commit将add的文件提交到本地仓库.git目录中,这里真正的合并到本地仓库.git目录里去。
git commit -m '第一次提交'
这里后面一定要跟日志'日志内容'
,不然就会报错
commit如果失败一般都是无法找到邮箱地址,没有配置好,配置一次就行了
如下图所示:
1.2.6push(推送)
push将本地仓库推送到远程仓库来进行同步。
git push
如下图所示:
push之后,gitee上的远程仓库.git就已经被本地仓库.git同步了。
打开gitee的仓库可以看到提交成功
对两个特殊情况的处理
处理完毕之后,是这样的
配置免密码push
git本地免密码和账号pull、push_没有git账号怎么拉代码-CSDN博客
1.2.7 log(获取提交记录)
输入下面指令来获得提交的记录
git log
1.2.8 status(获取仓库状态)
输入下面指令可以查看当前仓库更改状态,就是距离上次提交发生的变化。
git status
如下图所示:
这里先查看状态,然后修改文件名,然后再查看状态
commit发生改变的文件
然后再push
查看gitee的远程仓库,可以发现,只提交了readme.txt,ProCessOn.exe没有提交。
这是因为.gitignore里限制了.exe后缀结尾的文件。因此无法提交
1.2.9 mv(修改已在仓库的文件名)
再仓库里如果想修改一个已经提交了的文件的文件名,那么需要用到git mv
,而不能直接使用mv修改linux的文件名。
1.2.10 rm(删除已经在仓库的文件)
如果想删除已经在仓库中的文件,要用git rm
,并且还要commit,并且push,这样本地仓库和远程仓库才能都删除。
如下图所示:
1.2.11 pull(拉取远程仓库来同步本地仓库)
如果直接修改了诶远程仓库,那么下次从本地仓库推送的时候就会冲突。
pull存在的意义:
在多人进行开发的时候,其中一人在本地仓库push到远程仓库之后,对其他人来说,远程仓库就被修改了,和本地仓库不一致了。因此其他人想要push都得先pull拉取远程仓库来同步本地仓库才行
通过git pull
来拉取远程的仓库,来同步本地的仓库。
这个时候本地仓库在push就会冲突
这个时候就要pull来解决
pull完之后就正常了
注意,这里将远程仓库拉取到本地仓库,远程仓库的内容会同步到本地仓库的
我在远程仓库多加了一行空,pull之后,同步到本地仓库,下面将内容cat出来也可以看到
目前提交了这么多次,现在在log一下,可以感受到log的作用了
2.Linux调试器—gdb
目前为止,Linux的工具中,已经知道了下载用的软件包管理器yum,编译用的编译器gcc/g++,编辑器vim,自动化构建工具make/Makefile,还有版本控制器git。
接下来要了解的是Linux的调试器——gdb
调试,在window操作系统中,已经很熟悉了。但是window是图形化界面,linux在不连接VS等工具进行开发的话,是命令行界面。
因此对于命令行界面的调试就需要用到gdb。
关于调试的思路无论是在Linux还是window都是一样的
但是调试的操作方式就不一样了。在Linux叫做命令行调试
2.1gdb的使用
使用gdb得先确保当前linux系统中存在,没有就得下载
yum install -y gdb
普通用户sudo一下。
gdb的使用选项:
gdb binFile 退出:
ctrl + d
或quit
调试命令:list/l 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。
list/l 函数名:列出某个函数的源代码。
r或run:运行程序。
n 或 next:单条执行。
s或step:进入函数调用
break(b) 行号:在某一行设置断点
break 函数名:在某个函数开头设置断点
info break :查看断点信息。
finish:执行到当前函数返回,然后挺下来等待命令
print§:打印表达式的值,通过表达式可以修改变量的值或者调用函数
p 变量:打印变量值。
set var:修改变量的值
continue(或c):从当前位置开始连续而非单步执行程序
run(或r):从开始连续而非单步执行程序
delete breakpoints:删除所有断点
delete breakpoints n:删除序号为n的断点
disable breakpoints:禁用断点
enable breakpoints:启用断点
info(或i) breakpoints:参看当前设置了哪些断点
display 变量名:跟踪查看一个变量,每次停下来都显示它的值
undisplay:取消对先前设置的那些变量的跟踪
until X行号:跳至X行
breaktrace(或bt):查看各级函数调用及参数
info(i) locals:查看当前栈帧局部变量的值
quit:退出gdb
2.2gdb的使用案例
先通过vim来编写一段代码:
然后使用Makefile:
运行结果如下:
这是正常运行的情况,假设我们在编写代码的时候出了点错误。如下图所示:
这样结果就是4950而不是5050.
因此这个时候我们就要用gdb去调试,去找哪里出问题了
直接输入gdb test
但是无法调试成功
这里的no debugging symbols found
其实是**因为Linux中gcc默认编译出来的程序,是通过release生成了。而如果想要调试,是需要在debug模式下生成的。**这个在使用VS2022的时候也知道
为什么gcc默认使用release模式呢?
因为一个可执行文件大概率是给用户使用的,用户不需要也不会想要一个debug模式的可执行文件,它需要的是体积更小,优化更好,更好用的一个可执行文件。
debug模式是给程序员来方便进行调试的。
所以,让gcc编译的时候用debug模式就行
在gcc编译的时候添加一个-g
选项
然后make一下,debug模式的可执行文件test_debug就编译出来了
可以看到debug模式生成的可执行文件的大小肯定是大于release模型生成的可执行文件
拓展:readelf -S
判断一个可执行文件是debug还是release模式,可以用
readelf -S 可执行文件的文件名
比如test是release模式生成的可执行文件
执行
readelf -S test
的结果是这个图片是可执行文件test的二进制代码的一种表示方式。虽然可执行文件是一堆二进制代码,但是这堆二进制代码也是有格式的、
想要看懂这个表格需要汇编原理的知识,这里不需要看懂,只需要知道debug和release的可执行文件的表格的不同之处
接下来看debug生成的可执行文件test_debug
执行
readelf -S test_debug
的结果如下:如果是debug模式生成的可执行文件,那么其二进制代码中一定会有关于debug的一篇区域。
并且release模式生成的可执行文件,其二进制代码中不会有关于debug的区域
用gdb对test_debug进行调试:
输入gdb test_debug
2.2.1显示源代码
这里源代码本来也不多,按2次enter就可以将源代码全部显示出来
2.2.2打断点(VS的F9)
然后就按照调试的老规矩,打断点,开始调试
在gdb中打断点就是b + 行号 或者 break + 行号
如何查看断点呢?
输入info b
,可以看到之前打过的所有的断点的位置
2.2.3删除断点
如果不想要断点想删除就输入d 断点编号
2.2.4开始调试(VS的F5)
输入r(run)开始调试,会自动找到顺序执行代码的第一个断点的位置
这里跳到了位于25行的断点的位置。
2.2.4.1跳到下个断点
如果要从一个断点跳到下一个断点
输入c(continue)
这个过程就和VS有多个断点,要跳到下一个断点要再按一次F5是一样的
2.2.5逐过程(VS的F10)
输入n(next)
逐过程,不进入AddToVal函数内部,而是跳过
2.2.6逐语句(VS的F11)
输入s(step)
进入到Print函数内部,参数sum此时是4950,这说明代码是在AddToVal函数内部出问题的,打印是没有问题的,参数sum应该是是5050,而不是4950
此时再查看一次断点
这里多了一句话,意思是这个1号断点已经被命中一次了
此时如果要重新开始调试就在输入一次r
这个时候会问你是否要重新调试,输入y表示重新开始调试
2.2.7查看调用堆栈
但是这个时候我们发现在循环里面,无论是输入s还是n,都好像在不停的执行语句,无法调出监视窗口和函数堆栈。看不到变量的变化和变量的地址
【如果已经进入循环可以一直按回车】
因为gdb会记录最近一次指令,这里疯狂按回车相当于每次都是输入的s。
输入bt来查看函数堆栈
可以看出来是从main堆栈进入的AddToVal堆栈
2.2.7.1将当前堆栈运行完毕
如果我们既不想新打断点,跳跃过去,又想直接执行完一个函数。
就可以用到finish
此时就结束了当前堆栈的调用,相当于直接执行完了该函数,可以看到回到了25行。
这个是非常有用的,如果finsh之后,代码挂掉了,就说明是当前堆栈,当前函数有问题,就可以缩小调试范围了。
2.2.8监视变量(显示变量)
2.2.8.1p(监视单次变量)
输入p 变量名
可以监视变量
但是这个有个问题,只能监视一次变量,每次走一步都得重新输入p,重新查看,这样很麻烦,能不能像VS那样有个监视窗口的存在呢?
2.2.8.2display(常显示变量)
输入display
就可以实现
这里i就会一直挂在上面,方便调试。
将需要监视变量都display一下
就可以得到一个类似监视窗口一样的东西。可以直观看到每一步变量的变化
要查看地址就加个&
如果不想要监视某个变量就用undisplay
要注意取消监视变量,需要输入的是变量的编号
2.2.9跳出循环
如果进入了一个循环,循环很长,且认为问题不出在循环上,想要跳出循环,就输入until + 行数
。这里的行数得是循环外的
循环一直在14~16行,因此until到17行,相当于跳出循环了
2.2.10查看局部变量
输入info local
,来查看当前栈帧的局部变量的值
2.2.11禁用断点
输入 disable b 1
,表示禁用1号断点、
2.2.12启用断点
输入enable b 1
,表示启用1号断点
2.3gdb的总结
gdb的使用选项有特别多,使用起来也比较麻烦,但是最常用的几个选项能够使用就行了