前言:
我们今天来介绍一下我们工具篇的最后两个工具,即git提交指令以及代码调试工具gdb,再结合前面的知识点,我们就可以基本完成我们VS上的基本的功能:编写,调试,编译,执行程序的这些过程。
1.git指令,git的基本原理:
1.git的诞生:
git最早是LINUX之父雷纳兹托瓦兹开发的,用于对LINUX操作系统的代码维护的存储和更新,它可以用来自动管理全球各地提交的LINUX的代码进行一个统一的管理,雷纳兹可以从中进行测试从而用来扩展和更新代码。后来,基于git的功能和底层,又出现了各种各样的专门用来托管个人代码的网站,gite github等。到这里,我们的git软件已经不仅仅是服务器,同时它也是客户端了,既能满足客户的要求,同时又能实时的管理很多用户的代码。
2.git的作用-----版本控制器:
版本是我们再熟悉不过的词,每次我们玩游戏的时候,都会遇到版本更新的问题,版本更新意味着新的内容和功能的拓展,但是,我在这里的问题是,我们之前的旧版本就没了么?
不,我们之前的版本仍然存在,并且按照顺序合理的排列在我们的版本控制器中,我举一个简单的例子,魔兽世界不仅仅在实时更新,同时也有一个怀旧服。要知道,暴雪公司开发魔兽世界这样的一款极其复杂的游戏的代码量起码是百万以上,这意味着大量的财力和物力资源的倾斜,本质上来说,倘若重新去写旧版的魔兽世界,是一个十分亏本的计划。但暴雪却能迅速推出怀旧服并且让玩家去体验,这便是版本控制器存储了这个游戏的任意版本,只需要按照需求去重新重构版本搭建服务器即可运行。
由此,我们便总结出版本控制器git的真正作用:帮助用户/开发者根据需要提供任意版本。
但是,说到这里,我们可能会对git和gitee/github混淆:他们两个有什么区别呢?
你可以这样理解,git本身是一个软件,既是客户端,又是服务器,git是只会记录变化的软件,git是去中心化的,为分布式软件。基于git,我们开发出了gitee/github这样的网站,让我们的git去进行的版本管理可视化,而不是类似LINUX那样的用指令进行抽象的操作。
3.git的操作指令:
1.是否安装git检查:git --version
倘若没有安装:sudo(root) yum install -y git
2.将我们创建好的git仓库下载到LINUX本地:git clone +gitee网站的仓库地址(仓库的地址可以在gitee上查到)
3.git add .:将当前目录下未放入git库的文件放入git库(自动)
4.git commit -m "仓库上传日志“ :将带有日志的git库代码提交到本地仓库
5.git push:将本地仓库代码上传到远端仓库,在这一步需要我们输入用户名和密码,这个就看个人设置了,我个人的是手机号作为用户,密码是自己设的。
6.git pull:同步远端仓库和本地仓库
7.git status:查看本地仓库的干净状态,是否有没有上传远端仓库的文件
8.git log:查看自仓库配置好以来的代码提交历史
.gitignore文件(注意,别忘了这是隐藏文件,前面有一个.后缀)
.gitignore是用来清理没必要的文件上传到git上,如一些后缀为.o .d .ko这些,我们也可以自己向文件写入我们指定后缀的文件,写入后带有指定后缀的文件就不会被上传到远端仓库中,如下:
我们打开文件的内部,里面是这样的:
你看,在这里,我就补上了.cc的后缀,这样,我们创建的后缀为.cc的文件就不会被传入到远端的gitee仓库中,有了这个文件,我们就可以将不必要的文件传入到远端仓库,从而简洁了我们的源码的质量。
需要注意的问题:
我们push我们的文件,是需要我们的文件先和远端仓库同步的,否则上传无法执行,但是在多人开发中,开发者有的时候不仅仅是一位,可能多人同时在线开发,你是不知道他人是否push了新的文件的,故此时我们的方式是先push一次,倘若通过了,证明没人提交,你的提交成功了,反之则有人先提交了,则你需要先git pull同步一下仓库,然后再提交。或者你先git status看一看当前仓库的状态,从而判断是否需要同步,这两种办法都可以解决问题。
在LINUX下调试代码的工具—gdb:
我们写程序不仅仅是编写代码,对代码的后续维护和调试也很关键,而我前面曾经说到过,vim本身写下的软件是不具备调试功能的,需要我们后期自己去配置和使用另一个软件gdb去进行调试相关的功能。
首先我们明确一件事情,代码能被调试的环境一定是debug下的,只有在debug下我们才能对代码进行调试,代码的运行环境一共分为debug和realease两个版本,我们的用户所能体验到的版本一般是release下的,即取消了几乎全部的检验程序和各种调试性的程序,并且对递归进行了更深层次的优化的版本,所以,在这个版本下的程序的运行速度是很快的,在debug版本下,我们的程序运行速度并不快,但是可以去调试代码从而让代码进一步的更改和bug的更正。
对于一名程序员来说,我们要清楚我们自身在一个项目全部开发过程中的定位和职责是什么,我想用下面的一张图来演示:
由此,我们可以得出结论,一个合格的程序员在开发项目的过程中需要与各种各样的人沟通,这也考验着我们的语言沟通能力,故我们要刻意去培养这方面的能力。
在LINUX下使用gdb去调试代码:
首先我们要明确,在LINUX下,我们调试代码默认的都是release模式,这要是为什么我们vim去打开文件调整代码的时候我们没法去调试的原因,所以,想要调试代码,我们就需要让其可以更改为debug模式,这就需要我们在Makefile文件内部在执行我们的脚本自动化编译的时候自己加上一个-g 选项,如下:
但是,我的问题是:我们如何证明我们的LINUX代码默认为release模式呢?
1.首先我们要明确,debug模式下编译出来的可执行程序的大小是要大于release模式下编译出来的程序的,我们可以先后取消-g选项去进行一下测试,便可以得出结论。
如下面的这两个对比
**
2.倘若这样说明也很牵强的话,我们可以使用readelf -s 文件名|grep -i debug来寻找可执行程序中是否有debug模式的文件,倘若有就说明我们确实是手动加上了debug而不是自带的。**
补充:注意,我们在LINUX的可执行程序是有一定格式的,你可以看作是有一定规律的二进制代码,我称之为elf格式,用readelf可以去查看这个格式
故对应的指令为readelf -s 来读取对应文件的二进制构成
使用gdb的指令:
1.gdb +可执行程序文件:执行此编译程序的调试模式(注意这里不是源代码,而是可执行程序,别弄错了)
2.list/l:展示代码包括行号 l+数字:从指定位置开始展示代码,后续按回车就可以不断展示后面的源码直到显示出最后一行总结出代码的行数,说明整个代码被展现完成了
3.quit/ctrl+d:退出调试
4.run/r:不打断点直接执行程序->有点相当于vs的F5,即启动程序
5.b+行数/指定程序段的字母:打断点
6.info b:查看断点列表(若有多个文件,可以b+文件+行数:给对应的文件上的内容加断点)
7.d+对应的断点列表的编号:删除断点(注意,这里的断点是指对应的断点列表的编号,而不是行号,且断点编号是累加的,在一次调试中累加,调试结束则自动归零
注意:断点默认为y,即开启的状态
8.关闭断点:disable +断点编号,此时执行程序,此断点就不起作用了,启动断点:即enable+断电编号,此时断点重新生效
9.n/next:逐过程执行程序,有点类似vs里的F10
10.s/step:逐语句执行程序,有点类似vs里的F11
11.查看对应的变量:p+变量
12.display+对应的变量:随着程序的执行,常显示某个变量,有点类似vs里面的调试过程中一直对某个变量的变化进行观察
13.undisplay+对应的变量编号:取消常显示,与断点列表一样,undisplay后面也要加列表编号
14.until+行号:在函数程序内直接跳转至指定的位置
15.finish:运行到当前函数的结尾,并判断是否有错误,这里当然包括主函数main
16.c/continue:从一个断点处直接运行到下一个断点处
17.bt:调用堆栈查看
18.set var+变量:更改变量的数值,让其从对应数值的逻辑位置继续执行程序
19.info locals:将当前程序的变量体现出来
总结:
关于gdb和git,我们还有很多功能值得去探索,大家可以在看完这篇文章之后,先掌握基本的调试指令,然后自此基础上不断的去扩展,从而强化自己的调试能力,不过我觉得其实直接去看代码有的时候效果更好,反而调试效率变低的,但是调试这个能力我们是不能缺失的。
到这里,我们的全部的linux的代码编写工具就基本完成了,现在我们就可以用LINUX去编写我们的C/C++的代码了,下一步我们将进入进程篇,去体会计算机操作系统是如何去掌控软硬件的。