gdb
在windows下的vs2013下,我们可以进行调试,方便我们了解程序的具体的运行步骤和存在的问题,那么在Linux中,也存在这样一种调试机制,gdb就是在Linux系统下的调试指令。
Linux下和Windows下的调试的区别
答:调试的思路一定是一样的。
调试的方法一定是不同的,因为我们正常使用的Linux系统是没有可视化界面的,一般是以命令行的形式,所以Linux的调试方法和Windows一定会有所不同。
我们创建一个文件来进行gdb的练习操作:
我们创建一个普通文件mytest.c
我们使用vim对文件内容进行编辑
我们为了方便gdb的使用,写了三个函数块,main函数调用AddToVal函数,这个函数返回sum值,接下来,我们调用Print函数,这个函数打印sum和时间戳。
接下来,我们创建一个文件Makefile,使用vim来编辑依赖对象和依赖关系
我们对这些代码进行翻译:
mytest的依赖对象是mytest.c,表示mytest是由mytest.c生成的。
依赖方法是这样:使用gcc进行编译链接,把mytest.c源文件经过编译链接形成可执行程序mytest
.PHONY:表示声明我们的clean没有依赖对像。
依赖方法是删除mytest文件。
我们使用make,形成可执行程序
gdb指令:
下载指令:sudo yum install gdb
经过下载安装之后,我们可以使用gdb指令。
进行gdb调试:gdb加+可执行程序文件名
退出gdb调试:输入q
默认情况下,gdb无法对release版本进行调试,调试只能在debug版本下进行,在Linux系统下,gcc默认生成的可执行程序默认是release版本,所以无法进行调试,我们可以这样操作:
加上 -g表示gcc形成的可执行程序是mytest文件。
总结:gcc在默认使用时,使用的是动态链接
生成的可执行程序默认是release版本。
为什么软件发布要有两个版本?
答:release版本是留给用户使用的,用户并不需要调试或者了解调试方法,debug版本是留给程序员的。
debug版本相当于就是release版本下又添加了调试信息。
debug版本下,我们的文件占的内存是9816.
release版本下,我们的文件占的内存是8472.
gdb环境下的l
可以显示文件的内容
再输入空格,可以显示更多的文件的内容。
假如我们想要从最开始开始显示:
l +数字:
表示从第一行开始显示
假设我们要从第0行数字开始显示:
打断点b 加数字
例如:假设我们要在第9行设置一个断点,我们可以输入b 9
查看断点 info b
Num代表断点的编号
删除断点 d 编号
注意删除断点不能使用d +所在行
例如:假如我们要删除编号为1的断点,该断点在第九行,我们不可以用d 9 ,可以用d 1
我们删除断点之后再来查看断点:
调试运行:r
我们设置几个断点:
我们设置两个断点,一个在第20行,一个在第22行
我们输入r
逐过程:next
我们现在指针指向第20行,我们输入n,n表示逐过程:
函数的逻辑应该是进入sum函数,但是我们的n逐过程并不会直接进入函数。
逐语句:step
我们输入s,逐语句进行调试:
我们直接进入add函数。
c:表示从一个断点跳到下一个断点:
我们设置三个断点,分别在第19行 第20行 第21行
我们按下运行,跳到第一个7断点处
我们输入c
跳到下一个断点的位置。
bt查看函数调用堆栈:
我们设置22行的断点:
我们按下r,进行调试运行:
然后我们按下bt,查看函数调用的堆栈:
调用的是main函数的堆栈
finish直接跑完这个函数停下来:
我们设置一个新断点
在第5行,我们按下bt查看函数调用的堆栈
假如我们想要结束Print函数,我们输入finish
回车执行上一个指令:
我们输入l 1,然后再按回车
相当于执行l 1指令。
p命令查看变量对应的值
我们先设置断点在第9行(进入AddToVal函数的内部)
我们使用p来查看变量from和to的内容
display常显示变量
接下来,我们进行调试的时候,这些变量的值就能够常显示了。
对于地址,也是可以常显示了。
接下来,我们再进行调试:
undisplay:取消常显示变量:
注意:undisplay修饰的是编号:
我们继续调试:
我们常显示的变量就消失了。
until跳到指定行:
例如:
我们在第20行打一个断点
我们进行运行:
假设我们想要运行到第22行,我们输入until 22
接下来,我们就运行到了第22行。
p+变量名打印变量值:
我们设置第11行的断点,然后进行运行:
我们可以打印几个变量
set var+变量名:修改变量的值:
info locals显示局部变量:
我们在这一行,假如我们要显示局部变量的话,可以这样做:
进程:
冯诺依曼体系结构
这里的存储器指的是内存,内存具有掉电易失的性质。
磁盘可以叫做外存,具有永久性的存储能力。
磁盘也叫做外设,外部设备,外设非为输入设备和输出设备。
鼠标键盘等都是输入设备,显示器,打印机都是输出设备。
运算器+控制器组成cpu,存取速度块
存储器是内存,存取速度较快
外设存取速度较慢。
cpu智能被动的接收数据,这个数据来自于哪里?
答:从临时存储和永久存储中取。
为什么cpu只接受内存传递的数据,而不与外设打交道?、
答:本质是为了提高效率,因为cpu的存取速度大于内存大于外设,假设由外设向cpu输入数据时,速度由外设来决定,而外设的存取数据的速度非常慢,内存中天然的没有数据,外设的数据就被传到了内存中,内存就有了数据,当cpu读取过数据后,再把数据返回给内存,内存再定时刷新给外设。
操作系统的作用:
操作系统就是内存和外设之间的桥梁,内存和外设的交互策略由操作系统来决定。
结论:
1:cpu不和外设打交道,和内存打交道
2:所有的外设,有数据需要载入时,只能载入到内存中,内存有数据需要输出时,只能输出到外设中去。
程序运行为什么要加载到内存中去?
答:因为cpu要处理我们的代码的话,只能从内存中接收数据,所以我们的程序运行必须加载到内存中去。
cpu的组成:
cpu包括运算器和控制器,控制器相当于提示器,提示我们运算完成,输出完成信号。
运算器包括逻辑运算和数学运算,逻辑运算就是if语句等判断语句,数学计算就是二进位制的计算。
思考题:
答:假如我们输入了你好,首先是我们的键盘作为输入设备,输入你好给内存,内存再把数据传递给cpu,cpu经过加密处理和运算再把对应的二进位制数据返还给内存,内存再把数据传递给网卡,网卡存储了两份,一份刷新给我们的显示器,一份通过网络传递到另外一个计算机的网卡上,网卡把数据传递给内存,内存把数据传递给cpu,cpu经过加密运算和解析,把数据返还给内存,有内存数据给显示器,刷新到显示器上。
操作系统:
操作系统是一个进行软硬件资源管理的软件
为什么要管理?
答:通过合理的管理手段,为用户提供良好的环境。
通过操作系统,实现硬件和软件的交互,方便用户操作。