目录
一.gdb调试
1.1debug和release版本有什么区别?
1.2性能优化
1.3gdb的使用
1.4cgdb的安装
二.什么是硬件
三.冯诺依曼体系
四.操作系统(OS)
4.1理解操作系统
4.1.1操作系统是什么?
4.1.2为什么要有操作系统?
4.1.3 OS-银行
4.1.4OS如何管理
理解库文件和系统接口
一.gdb调试
默认系统上应该是没有gdb的;root用户可以使用下面的指令安装;如果没有权限的话,那就sudo;
yum install -y gdb
ubuntu用户使用下面的指令安装
sudo apt install -y gdb
程序的发行方式有两种:debug/release版本;gdb的调制对象是debug版本的程序;
在linux下C/C++默认编译后产生的可执行文件是release版本;所以我们需要使用-g选项来编译为debug版本;
gcc -g code.c -o code#这里我以code.c文件为例
1.1debug和release版本有什么区别?
debug和release版本的区别在于debug版本相对于release添加了调试信息;这也就意味着debug中的东西比release多,所占空间更大;
我们可以看到默认编译下的code是release版本的,他所占的内存是8328;而debug版本下的debug_code是10880;这就是两者在内存上的区别;
1.2性能优化
release下编译器可能会对程序代码的内存空间进行优化,就比如之前类和对象中的连续拷贝问题(隐式类型转换),在debug版本下会先产生临时变量,再赋值给目标对象;但是在release版本下就会优化为不产生临时变量
1.3gdb的使用
命令:gdb + 可执行程序
1.代码展示
lilst/l +行号 展示该行源代码,
list/l + 函数名 展示函数的源代码
在不加行号的情况下,每次l会列出10行,直到列完;
如果l +行号,就会把该行展示在中间部分,
2.执行语句操作
r或run:运行程序(默认会直接结束或者跳到下个断点)相当于vs 中的"继续";
n 或 next:把函数当成一个语句(逐过程),就是不进入函数内部;
s或step:不会跳过代码块(逐语句)遇到好函数就会跳转到内部;
3.设置断点
break(b) 行号:在某一行设置断点
break(b) 函数名:在某个函数开头设置断点
info(i) break(b) :查看断点信息。
delete breakpoints:删除所有断点
delete breakpoints n:删除序号为n的断点
disable breakpoints:禁用断点
enable breakpoints:启用断点
1.设置并查看断电
设置断点:b +行号/函数名 查看info b
2.关闭断点
disable + 断点编号
我们发现关闭断点之后keep处由y-->n;这就是断点开关标志;有的时候我们只是暂时不需要这个位置的断点,以后可能还会用到,所以没必要删除断点(删除断点和关闭断点是不一样的);
3.打开断点
enable + 编号
4.如何删除断点
delete
控制变量
p 变量:打印变量值。
set var:修改变量的值
display 变量名:跟踪查看一个变量,每次停下来都显示它的值
undisplay:取消对先前设置的那些变量的跟踪
breaktrace(或bt):查看各级函数调用及参数
info(i) locals:查看当前栈帧局部变量的值
1.手动查看变量的值
2. 跟踪变量的值(监视)
每次执行一条语句都会自动显示n的值
3.设置变量的值(强制修改)
set var 变量=值
跳转定位
finish:执行到当前函数返回,然后挺下来等待命令(走到该函数最后)
until X行号:跳至X行(方便我们快速跳出循环)
continue(或c):从当前位置开始连续而非单步执行程序(帮助我们从当前断点直接跳到下一个断点)
run(或r):从开始连续而非单步执行程序(向下运行程序)
退出调试
q/quit
1.4cgdb的安装
命令:sudo apt install -y cgdb
其余操作与gdb一样;
优点:可以随时看到源代码;
二.什么是硬件
硬件就是看得到摸得着的计算机外部设备;我们使用的笔记本和台式电脑就是各种硬件的组合,其中包括CPU,显示器,磁盘,网卡,内存,键盘...
单看他们仅仅只是一堆物件,需要之间相互建立联系,才能是设备工作起来,而这整个系统就是冯 诺依曼体系;目前的任何计算机设备都采用的是冯诺依曼体系;
发明冯诺依曼体系的人简直就是天才,讲一堆的物件按照体系进行配置安装,使得每一项硬件都可以发挥更好的作用;这是在计算机领域是一项十分伟大的发明;
三.冯诺依曼体系
输入设备:键盘,鼠标,摄像头,触控板等......
输出设备(外设):显示器,磁盘,打印机,耳机等;
存储器:就是指的内存,寄存器.CPU(中央处理器):
运算器:对数据进行运算,比如+,-,*,/,%等...
控制器: 控制输入和输出设备(外存).
强调:
1.存储器说法太官方,其实就是指的内存
2.红色的线指的是数据线;单论数据上,CPU在体系中只能跟内存打交道,对内存进行读写;
3.黑色的线指的是控制线,CPU其实是可以直接向外部设备发送信号的,比如让磁盘启动/停止/降速/读取..;
4.外设也只能跟内存打交道,写数据到内存中,从内存中读取数据;这就是为什么C语言中要有缓冲区的原因;缓冲区就是一块内存;
总结:内存就如同整个体系的一条必经之路,所有的设备都要与内存建立联系;
问题1:我们的文件是在哪里存储的?
在过去我们写过很多的C/C++等文件,这些文件其实是在磁盘上存储的,磁盘是什么?磁盘是外设;在举个例子,我们的U盘,就是用来保存和存储文件的;
任何程序要运行都需要先加载到内存中,这个其实是OS(操作系统)接受程序员的指令,通过特定的系统接口驱动硬件;此时硬件就是输入设备,只有将数据搞到内存中,CPU才能对数据进行处理和控制;
问题2:为什么必须加载到内存?
文件的本质是代码和数据,代码是需要CPU执行的,运算是需要运算器计算的,总之,文件将来是一定要被CPU读取的;而在数据上,CPU只会访问内存(红色的线),所以文件运行时,就一定要加载到内存中去,这就是冯诺依曼体系所规定的;
问题3:我要做IO,怎么理解?
IO就是input和output,这里肯呢个有人会有疑问了,我们的IO流输入输出不是scanf/cin和printf/cout吗,怎么是input和output呢,其实两者都是的,只是站的角度不同;
scanf/printf那是代码,实在程序的层面上,而程序是什么?程序是文件,是需要加载到内存中的;我们使用的scanf其实就是从键盘读取数据到内存中,在冯诺依曼体系中,这个过程就是input;
问题4:假如你在北京,你朋友在上海,你们在QQ聊天,请分析下你们的数据流向.
我们的电脑都是冯诺依曼结构,我们都需要先登录qq,qq是一个可执行程序,打开qq就是把QQ加载到内存中;然后我通过键盘输入数据,这个过程就类似于scanf输入;数据然后到达内存qq中,然后再传输到显卡;传输到朋友的输入设备;对于朋友的电脑而言,输入设备及就是你的网卡,最后经过CPU在朋友的电脑显示器上出现信息;
问题5:为什么要有内存?
明明储存器的数据就是外设传递的数据,那我为什么不能直接让外设连接CPU呢,这样岂不是简化了体系了;
这与CPU和外设的处理数据的速度相关;如果CPU处理数据的速度是ns,那外设的速度就是ms;这样一对比,CPU的速度就是外设的100万倍;根据木桶原理,这个时候,计算机的效率就会取决于外部设备,效率很慢;
在计算机中有一个规则:
硬盘离CPU是很远的,他的速度是很慢的,但是他便宜,而寄存器就比较快了,如果我们让CPU从寄存器中读取数据,那这个速度就会相对提高;
这里如果我们上述三者理解为串型了,那根据木桶原理根本就没有解决任何问题;但实际上,CPU在处理外部设备的数据时,同时也在处理其他的数据;并不是仅仅等着外设传输的数据;这是一个并型结构;
所以为什么叫存储器,是用来暂时存储数据的;
举个例子:老师在班上说周日要交实验报告,同学们谁先写完了就放到办公桌上;放到办公桌上这就相当于是在输入数据,办公桌就是一个存储器;但是同学们去交报告时,难道老师要一直在办公室等着吗?这显然是不可能的,老师也有他自己的事要去做;老师就相当于是CPU;有了办公桌,这样等老师回来的时候,就可以批改了;老师批改的速度是很快的,但是同学们可能有的周二交,周三交,甚至周末交;速度是很慢的;如果没有办公桌这样的存储器就没有地方可以存储数据,那可能会造很多的问题,难受的不仅是老师还有同学;所以存储器/内存是必要的;
四.操作系统(OS)
4.1理解操作系统
4.1.1操作系统是什么?
操作系统最重要的部分是内核,而我们需要使用操作系统的外壳来跟内核打交道;
内核:进行着进程,任务,线程管理,文件系统,内存管理,驱动管理等;
我们程序员都是通过外壳来下达指令,操作系统帮我们处理指令,驱动硬件等..我们下达的指令就是代码,然后通过操作系统的系统接口,来让操作系统帮我们执行;OS更像是一个管家;
本质:是一款进行软硬件管理的软件! linux内核就是用C语言写的;
4.1.2为什么要有操作系统?
计算机软硬件框架层级关系:采用冯诺依曼的结构构建;
每一种都要有自己的驱动程序,操作系统是不会直接访问硬件的;有些驱动程序是我们买电脑是就已经配置好的;驱动程序就相当于是操作系统的触手,可以摸到硬件;
给用户提供良好稳定的运行环境
我们使用计算机的目的,肯定是要连接现实生活的东西的,不然总是虚拟的,并没有太大用处;所以最终的行为都是在硬盘上体现的;
当我们将买的鼠标插到电脑上时,我们会发现并不能马上移动,虽然物理上已经与电脑连接但是这个时候驱动程序还没有被加载好;是无法驱动硬件的;驱动程序就是操作系统跟硬件打交道的软件;
OS是一个帮助我们管理软硬件资源的角色,但这仅仅只是他的手段罢了,他的目的是为了给用户提供一个良好(稳定、高效、安全)的运行环境,但我们要知道其实普通用户是不善于和OS打交道的,所以普通用户使用的都是基于程序员开发出来的软件,所以首先是我们专业的程序员需要去跟OS打交道,然后再搞出满足普通用户需求的各种软件!
4.1.3 OS-银行
前面讲了,操作系统的目的是给用户提供良好的运行环境,但其实操作系统是不信任用户的;
现在把操作系统比作是银行,今天张三来存钱,整个流程都是他自己操作的,存钱,登记信息等,,,但是如果很多人都无规矩的这么做,那我银行的安全性岂不是很差,万一有些人不怀好意把我电脑数据清楚了,我找谁说理去;所以在来的客户中,有好人也有坏人,OS是不认识的,为了安全着想,所谓行长就设立的窗口,存钱就到窗口1,取钱就到窗口2,查询就到窗口3...这样就可以保证我内部数据的安全性;这些的小窗口对应的就是OS给用户提供的各种的系统调用接口;
这些接口是设计者设计的,只有我们通过特定的接口,我们的指令才会有效;
但是呢,有些老年人岁数大了,什么都不懂,字都不认识,更不要说银行复杂的业务流程了;那这个时候行长就在门口接待处设置一些辅助人员,一边帮他们更好的完成业务;
这对我们程序员也是一样的,如果直接去使用系统接口,我们是看不懂,不会用滴,所以大神们针对问题设计出了一些软件,来让我们使用;
4.1.4OS如何管理
操作系统为了更加方便的管理软硬件,就把各种的硬件的属性以及硬盘上的信息使用C语言的结构体包装,这就能很好的描述一个物体;
那么既然OS管理对象是使用的结构体,数量又这么多,所以OS就干脆使用链表把所有的信息串起来;这样更加方便管理,从管理者的角度这不就是数据结构吗?那对数据的操作就是增删查改!
理解库文件和系统接口
先举个例子,假如有A和B两个校长,A校长有一个学生数学特别厉害,但是B校长没有,于是B校长就想跟A校长商量借这个同学来打比赛,但是B校长肯定不能直接去找这个学生,因为这个学生是A校长的人,他得负责,所以他必须要通过A校长的同意才行。
同理我们通过printf把“hello”打在屏幕上,其实并不是我们直接通过调用这个库函数就和硬件打交道了,而是必须要自上而下贯穿下去,也就是要通过系统调用接口然后让OS知道!!!
所以我们知道了库函数必须通过系统调用接口才能找到OS,所以库函数和系统调用是上下层的关系,库函数是基于系统调用之上的二级开发!