Linux环境基础开发工具使用(yum软件安装工具的使用、vim编辑器使用及握gcc/g++编译器的使用等下)

简介: 程序的发布方式有两种,debug模式和release模式

4.Linux调试器-gdb使用


4.1 背景


程序的发布方式有两种,debug模式和release模式

Linux gcc/g++出来的二进制程序,默认是release模式

要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项


4.2 开始使用


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


4.3 理解


首先我们建立一个test.c文件,然后进行编译,代码如下:


c947139c28824686884693521e52b1d8.png


但是我们要知道的是,在gcc或g++环境下默认生成的是动态链接release可执行文件,也就是说,他无法进行调试

我们可以在编译时加上-g,即指令gcc test.c -o testdebug -g

我们可以通过readelf -S 文件名的方式来查看两个可执行文件有何不同

默认生成的test可执行文件readelf -S test


be5a6747e8a14df9bf47a3888c5ccda2.png


生成的debug文件readelf -S testdebug


5946dfc5f6884e92a2fccab719cbeece.png


可以看到第二个文件是包含调试信息的,而第一个没有,所以第二个文件才能使用gdb进行调试


第一步我们输入指令gdb testdebug开始调试


ba0ee71b2bea46f083603f3c330ac02c.png


需要注意的是gbd会记录最近一条命令,如果命令无变化,可以直接回车

比如我们先显示所有代码从头开始打印输入l 0


d05630301dac4c028d79319ed70cb220.png


输入指令b 行号打断点


383a3f05c79642f58e9ae8fbcf608924.png


输入指令info b查看断点


c269d094e4474c4e9ef784f83ebc3c09.png


输入指令d 断点编号删除断点,记住不是行号而是查看断点中的num编号


8d45470393a242b29ec55a1f659deb8c.png


然后我们输入指令r开始调试,如果没设置断点,则直接运行结束


2b4dafc5d7ef477e899341fed3c57402.png


然后我们在执行函数前打一个断点,输入指令s为逐语句,输入n为逐过程


14505ce0eb0e4747b2d58ca70c14d69e.png


输入指令bt查看当前调用堆栈


ee99cab793c3447f9fb386863271b5e4.png


输入指令p 变量名打印变量内容,或者指令p &变量名查看地址


58cc809d10404d198b621f34037a4e16.png


如果你想常显示输入指令display 变量名,取消常显示输入指令undisplay


ee204700a4f148f383e280747e534d41.png

61d719aae8254b17b9d83f208eb00535.png


输入指令finish当前函数直接跑完再停下来


13a233315f6a4ce6aa0c7a9eb3b2e3ee.png


或者还可以输入指令until 行号直接跳转到某一行


54090dd992a444499bc98e39a88433cf.png


再比如下面我们多打几个断点,执行命令c直接运行到下一个断点停下来


875e31f5286d449b85edd57bf60d63a1.png

37312647b9b24e869337249c98596180.png


执行命令disable/enable 断点编号能关闭/打开断点


ea70b122e1e94f36a697696e773ec07d.png


最后执行命令quit退出gdb调试工具


ee4dd612fda1401da6c12e23854ff634.png


所有基础gdb调试命令就这些啦!


5.Linux项目自动化构建工具-make/Makefile


5.1 背景


会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力


一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作


makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。


make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。


make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。


5.2 理解


首先我们先在c文件的同目录下建立一个Makefile文件(首字母大小写均可)

输入touch Makefile


d1264766fe774633b4e352b5b33a42a8.png


我们打开Makefile文件输入下面信息后保存退出


  1 tests:test.c
  2   gcc test.c -o tests 
  3 .PHONY:clean
  4 clean:
  5   rm -f tests


1ebe4797d7044f4981ecc6b8923dbaa8.png


这段代码中第一行test是我们自己定义的Makefile命令,指向test.c文件,其为依赖关系,只有执行对应的指令,才会执行相对应的依赖方法,第三行中的.PHONY为伪目标定义,使得clean命令可以重复执行。

下面我们看如何使用这两个makefile命令

如果我们直接输入make则直接默认执行第一条命令


fe6a818b720f4118bc6cd81868ae1659.png


当然我们也可以使用make tests


34b0b78f593742ae91f1f051da2e5dc2.png


我们再执行第二条命令make clean


cee3de7c81df4de5ac83b5ae2c02ec0a.png


在这里我们需要注意的是,如果重复使用第一条命令,则会出现下面的情况


96c69ff9d45442c1a3dac63cb7122e90.png


这是因为我们的tests文件修改时间晚于test.c文件,所以它默认tests文件不必重新生成


cbc6c8448fbb4c029b27a7e2b97f3fdb.png


如果我们对test.c文件进行修改,再调用第一条命令,则可以重新调用


626a26dec19640419a25d07c2429168b.png


可以看到此时test.c文件最近修改时间比tests文件要更晚,此时我们再调用make指令


46be2657da6c46fca7efcd04ac6b2bac.png


5.3 实例代码


首先我们建立三个文件,如下:

test.h


  1 #pragma once 
  2 #include<stdio.h>
  3 
  4 extern void show(); 


test.c


  1 #include"test.h"
  2 void show()
  3 {
  4   printf("hello linux!\n");                                                                                                                                                                                                      
  5 }   


code.c


  1 #include"test.h"
  2 
  3 int main()
  4 {
  5   show();                                                                                                                                                                                                                        
  6   return 0;                                                                                                            
  7 }  


我们再将Makefile文件修改一下,如下:


  1 test:test.o code.o
  2   gcc -o tests test.o code.o
  3 test.o:test.c
  4   gcc -c test.c -o test.o
  5 code.o:code.c
  6   gcc -c code.c -o code.o
  7 
  8 .PHONY:clean
  9 clean:
 10   rm -f *.o tests  


保存后退出

我们输入命令make


9a241fd2de8e4d6fab022b95f77ba6e5.png


执行命令make clean


e472234012ae4ad1b9336bbbeac20d02.png


最开始的test命令下对应的是两个.o文件,但是目录下并没有,那么它会继续向下寻找依赖关系,执行依赖方法。


5.4 原理


make是如何工作的,在默认的方式下,也就是我们只输入make命令。那么,


1.make会在当前目录下找名字叫“Makefile”或“makefile”的文件。

2.如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“tests”这个文件,并把这个文件作为最终的目标文件。

3.如果tests文件不存在,或是tests所依赖的后面的test.o及code.o文件的文件修改时间要比tests这个文件新(可以用 touch 测试),那么,他就会执行后面所定义的命令来生成tests这个文件。

4.如果tests所依赖的test.o和code.o文件不存在,那么make会在当前文件中找目标为test.o和code.o文件的依赖性,如果找到则再根据那一个规则生成test.o和code.o文件。(这有点像一个堆栈的过程)

5.当然,你的C文件和H文件是存在的啦,于是make会生成 test.o和code.o文件,然后再用 test.o和code.o 文件声明make的终极任务,也就是执行文件tests了。

6.这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。

7.在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。

8.make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。


5.5 项目清理


1.工程是需要被清理的

2.像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译。

3.但是一般我们这种clean的目标文件,我们将它设置为伪目标,用 .PHONY 修饰,伪目标的特性是,总是被执行的。

4.可以将我们的 tests 目标文件声明成伪目标,测试一下。


5.6 Linux第一个小程序-进度条


首先我们创建Makefile文件并进行编辑保存


  1 proc:proc.c
  2   gcc -o proc proc.c
  3 .PHONY:clean
  4   rm -f proc  


创建proc.c文件


#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
  int i = 0;
  char bar[102];
  memset(bar, 0 ,sizeof(bar));
  const char *lable="|/-\\";
  while(i <= 100 ){
    printf("[%-100s][%d%%][%c]\r", bar, i, lable[i%4]);
    fflush(stdout);
    bar[i++] = '#';
    usleep(10000);
  }
  printf("\n");
  return 0;
}


保存好执行make


4d0b0ae670cd44929c979d6063ad7182.png


运行proc


9183f33028d8410d874fde5e4d571b54.gif


6.Linux上git的使用


首先我们在命令行输入git -v查看是否安装git


6d5c6652e2bf4cf1affcde62839271d9.png


若没有安装先执行sudo yum install -y git

因为作者使用的是GitHub托管代码,如果是gitee方法也大同小异

首先我们先建立一个项目仓库,用于测试


d17d975cf9d446e9afa7d024b274f76d.png


这两个选项都是用于建立新项目仓库


e7dd152ea77a495f8d77864f55e2b3b9.png


接下来我们拷贝该仓库的本地链接


8d3f271f96ef41aea6fd105d518f3628.png


下面我们回到Linux,进行第一步操作git clone 刚刚复制的仓库链接


0656d59ec2234d928d100d79210476de.png


接下来我们访问同名目录


c3d9bea76f7b4c5fa4d5e342d7b75048.png


现在我们可以将自己的代码上传,第一步上传代码到本地

git add test1.c

再写提交日志

git commit -m "这是一个测试代码"


58c0c69cc4d94157ada3b50498903935.png


再进行push上传,输入git push


1ab894cd66dd40c1a3eb83637a77e01d.png


需要注意的是,在push过程中,要输入用户名和密码,但是现在GitHub不支持密码方式push,所以我们需要创建一个令牌,用令牌代替密码即可成功push(getee用户不需要)


令牌设置


d5c3ef7d03ba408a84d6970408f29eaa.png


往下滑动可以找到


12e95da002974ef7809ccfea3c2db43c.png


因为我这是创建过的,所以可能有些不同,没创建过的应该只有一个按钮


483228a7f12e4bd2b7f5b8545c6a2091.png


有可能直接就是下面的页面


585852836a9042d48436a315ae59412e.png


3ee9687804e74e2fa95f4b347ae7c09b.png


记得复制好,放到记事本或者其他可以记录的地方,下一次进来就看不见了


a6d5679711e54c56b1877bba39531fdf.png


下次上传直接用这个令牌就行啦


d9aefac769634efea951f65266d7a444.png


c69096eddf1b4652be6e1f47f3e0b75f.png


还有一种其他的情况,如果在别的设备上我们更改了GitHub上该仓库内容,可能我们直接进行push会碰到下面的情况


43ec6d552da4437eb8aaa7227d22a1be.png


GitHub的仓库有了另一个文件,但是我的本地仓库并没有,此时我们建立一个新文件上传,看看会发生什么


9add226e290446ed9cd2a7691e8fa487.png


可以看到我们上传失败了,这是因为本地仓库和平台出现了不匹配的情况,也就是发生了冲突,这个时候我们直接无脑

git pull


268a4fcb1ebc4df4bfb663de127933d0.png


然后我们再进行上传


2d584ccba487464f94c347294aa5b656.png


d54c8ffb1dcf4023809a2f31ade62ce0.png


关于.gitignore文件我们可以自己进行编辑修改,主要目的就是在以目录文件形式上传时,过滤掉不需要的文件


b3fa3f513bca4d4d9545b4933ec2ce63.png

468de959c93f4dc9b2e0256269cf3d5e.png


我添加两个后缀名为.x和.X的信息,下面我们创建一个目录,包含一些文件


fd9f00fec24f45c493a682649be7c515.png


我们可以看到再进行commit命令时,本地已经将.x和.X文件忽略了


347119b1a3bc4e25b46fc6215fddc71b.png


我们再看GitHub仓库同样没有上传


7a1c6a9d5f99405ca83835e14f6dd4a7.png


结语


有兴趣的小伙伴可以关注作者,如果觉得内容不错,请给个一键三连吧,蟹蟹你哟!!!

Linux两万两千多字的文章,花了我很多时间和精力!!!

制作不易,如有不正之处敬请指出

感谢大家的来访,UU们的观看是我坚持下去的动力

在时间的催化剂下,让我们彼此都成为更优秀的人吧!!


21ac207e9eab42afad47043cd7b92dc9.png

相关实践学习
CentOS 7迁移Anolis OS 7
龙蜥操作系统Anolis OS的体验。Anolis OS 7生态上和依赖管理上保持跟CentOS 7.x兼容,一键式迁移脚本centos2anolis.py。本文为您介绍如何通过AOMS迁移工具实现CentOS 7.x到Anolis OS 7的迁移。
相关文章
|
2月前
|
监控 Unix Linux
Linux系统工具
Linux系统工具
47 6
|
2月前
|
监控 Java Linux
Linux系统之安装Ward服务器监控工具
【10月更文挑战第17天】Linux系统之安装Ward服务器监控工具
55 5
Linux系统之安装Ward服务器监控工具
|
2月前
|
JSON JavaScript Linux
Linux系统之安装cook菜谱工具
【10月更文挑战第15天】Linux系统之安装cook菜谱工具
38 2
Linux系统之安装cook菜谱工具
|
29天前
|
缓存 监控 Linux
Linux性能分析利器:全面掌握perf工具
【10月更文挑战第18天】 在Linux系统中,性能分析是确保软件运行效率的关键步骤。`perf`工具,作为Linux内核自带的性能分析工具,为开发者提供了强大的性能监控和分析能力。本文将全面介绍`perf`工具的使用,帮助你成为性能优化的高手。
92 1
|
29天前
|
缓存 监控 Linux
掌握Linux性能分析:深入探索perf工具
【10月更文挑战第26天】
30 1
|
2月前
|
Ubuntu Linux
Linux中软件安装问题
【10月更文挑战第4天】
24 1
|
3月前
|
存储 Linux Shell
常用vim命令和vim基本使用及Linux用户的管理,用户和组相关文件
这篇文章介绍了Vim编辑器的基本使用、常用命令和模式,以及Linux系统中用户和组的管理方法,包括用户和组相关文件如/etc/passwd、/etc/shadow和/etc/group的说明。
常用vim命令和vim基本使用及Linux用户的管理,用户和组相关文件
|
3月前
|
Linux
linux之centos安装dataease数据报表工具
linux之centos安装dataease数据报表工具
|
1月前
|
运维 监控 Shell
深入理解Linux系统下的Shell脚本编程
【10月更文挑战第24天】本文将深入浅出地介绍Linux系统中Shell脚本的基础知识和实用技巧,帮助读者从零开始学习编写Shell脚本。通过本文的学习,你将能够掌握Shell脚本的基本语法、变量使用、流程控制以及函数定义等核心概念,并学会如何将这些知识应用于实际问题解决中。文章还将展示几个实用的Shell脚本例子,以加深对知识点的理解和应用。无论你是运维人员还是软件开发者,这篇文章都将为你提供强大的Linux自动化工具。
|
3月前
|
人工智能 监控 Shell
常用的 55 个 Linux Shell 脚本(包括基础案例、文件操作、实用工具、图形化、sed、gawk)
这篇文章提供了55个常用的Linux Shell脚本实例,涵盖基础案例、文件操作、实用工具、图形化界面及sed、gawk的使用。
604 2