目录
linux项目自动化构建工具 - make/makefile
linux软件包管理器 - yum
linux下安装软件的方式
在 linux 系统中,安装软件的方法主要有以下三种:
-
编译源代码:从网络上下载软件的源代码,然后自行编译生成可执行程序。这种方式适合高级用户,可以根据需要进行深度定制。
-
使用 rpm 包:获取 rpm 安装包,然后通过
rpm
命令进行安装。这种方法不解决软件的依赖关系,适合安装单个独立的软件包。 -
使用 yum 包管理器:通过
yum
命令进行软件安装。这是最常用的方法之一,因为它会自动处理软件的依赖关系,简化了安装过程。
认识yum
yum 是 fedora、redhat 和 centos 系统中的前端软件包管理器。它可以自动从指定的服务器下载并安装 rpm 包,自动处理依赖关系,并一次性安装所有必需的软件包,省去了手动逐个下载和安装的繁琐过程。
注意:一个服务器同一时刻只允许一个yum进行安装,不能在同一时刻同时安装多个软件。
因为yum是从服务器上下载rpm包,所以在下载时必须联网,可以通过ping指令判断当前云服务器是否联网。
查找软件包
通过 yum list 命令可以罗列出当前一共有哪些软件包. 由于包的数目可能非常之多, 这里我们需要使用 grep 命令只筛选出我们关注的包. 例如:
yum list | grep lrzsz
结果如下:
lrzsz.x86_64 0.12.20-36.el7 @base
安装软件
指令: sudo yum install 软件名
sudo yum install lrzsz
yum会自动找到都有哪些软件包需要下载,这时候敲“y”确认安装,当出现“complete”字样时,说明安装完成。
注意事项:
1)安装软件时由于需要向系统目录中写入内容,一般需要sudo或者切换到root账户下才能完成。
2)yum安装软件只能一个装完了再装另一个,正在使用yum安装一个软件的过程中,如果再尝试用yum安装另外一个软件,yum会报错。
如何实现本地机器和云服务器之间的文件互传
既然已经安装了lrzsz,这里就顺便说一下lrzsz如何使用。
指令: rz -e
通过该指令可选择需要从本地机器上传到云服务器的文件。
指令: sz 文件名
该指令可将云服务器上的文件下载到本地机器的指定文件夹。
卸载软件
指令: sudo yum remove 软件名
yum会自动卸载该软件,这时候敲“y”确认卸载,当出现“complete”字样时,说明卸载完成。
linux编辑器 - vim
vim的基本概念
vim是一个功能强大的文本编辑器,特别适用于编写和编辑代码。
vim下各模式的切换
指令: vim 文件名
russleo@virtual-machine:~/russleo$ vim test.c
进入vim后默认为命令模式(普通模式),要输入文字需切换到插入模式。
这些快捷键和操作方法是vim中使用频率非常高的基础操作,熟练掌握它们能够极大提升编辑效率和流畅度。
vim命令模式各命令汇总
vim底行模式各命令汇总
在使用底行模式之前,记住先按「esc」键确定你已经处于命令模式,再按「:」即可进入底行模式。
vim的简单配置
关于vim配置文件的位置和作用范围如下:
-
系统级配置文件:位于
/etc/vimrc
,这是系统中公共的配置文件,对所有用户都有效。系统管理员可以在这里设置全局的 vim 配置选项,影响所有用户的 vim 使用体验。 -
用户级配置文件:位于每个用户的主目录下,路径为
~/.vimrc
。例如,用户xxx
的私有配置文件路径为/home/xxx/.vimrc
。这是用户私有的配置文件,只对该用户有效。用户可以在这里设置个性化的 vim 配置选项,如显示行号、设置键盘映射、定义命令别名等。
vim的配置比较复杂,某些vim配置还需要使用插件,建议不要自己一个个去配置。比较简单的方法是直接执行以下指令(想在哪个用户下让vim配置生效,就在哪个用户下执行该指令,不推荐直接在root下执行):
在csdn上有很多关于vim配置的文章,配置完成后,像什么自动补全、行号显示以及自动缩进什么的就都有了。
linux编译器 - gcc/g++
gcc/g++的作用
gcc和g++分别是gnu的c和c++的编译器。
gcc/g++语法
预处理
russleo@vm-0-2-ubuntu:~/test$ gcc -e test.c -o test.i
- 预处理功能主要包括头文件展开、去注释、宏替换、条件编译等。
- 预处理指令是以#开头的代码行。
- -e选项的作用是让gcc/g++在预处理结束后停止编译过程。
- -o选项是指目标文件,“xxx.i”文件为已经过预处理的原始程序。
编译
russleo@vm-0-2-ubuntu:~/test$ gcc -s test.i -o test.s
- 在这个阶段中,gcc/g++首先检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,将代码翻译成汇编语言。
- 用户可以使用-s选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。
- -o选项是指目标文件,“xxx.s”文件为已经过翻译的原始程序。
汇编
russleo@vm-0-2-ubuntu:~/test$ gcc -c test.s -o test.o
- 汇编阶段是把编译阶段生成的“xxx.s”文件转成目标文件。
- 使用-c选项就可以得到汇编代码转化为“xxx.o”的二进制目标代码了。
链接
russleo@vm-0-2-ubuntu:~/test$ gcc test.o -o test
- 在成功完成以上步骤之后,就进入了链接阶段。
- 链接的主要任务就是将生成的各个“xxx.o”文件进行链接,生成可执行文件。
- gcc/g++不带-e、-s、-c选项时,就默认生成预处理、编译、汇编、链接全过程后的文件。
- 若不用-o选项指定生成文件的文件名,则默认生成的可执行文件名为a.out
静态库与动态库
函数库一般分为静态库和动态库两种:
- 静态库是指编译链接时,把库文件的代码全部加入到可执行文件当中,因此生成的文件比较大,但在运行时也就不再需要库文件了,静态库一般以.a为后缀。
- 动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件当中,而是在程序运行时由链接文件加载库,这样可以节省系统的开销,动态库一般以.so为后缀。
gcc和g++默认生成的二进制程序是动态链接的,我们可以使用file指令进行查看。
其次,我们还可以使用ldd指令查看动态链接的可执行文件所依赖的库。
虽然gcc和g++默认采用的是动态链接,但如果我们需要使用静态链接,带上-static选项即可。
russleo@vm-0-2-ubuntu:~/test$ gcc test.c -o test_s -static
此时生成的可执行文件就是静态链接的了。
我们可以查看源代码相同,但链接方式不同而生成的两个可执行程序test和test_s的大小。这也证明了动态链接比较节省空间,而静态链接比较浪费空间。
linux项目自动化构建工具 - make/makefile
make/makefile的重要性
撰写makefile的能力对于大型软件工程的管理至关重要,它不仅反映了一个开发者对项目结构和构建流程的理解深度,还体现了其能否高效地处理复杂工程的能力。在大型项目中,源代码文件数量庞大,根据类型、功能或模块被精心组织在不同的目录下。此时,makefile就像一个指挥家,通过预定义的规则,有序地安排文件的编译顺序,甚至执行更为复杂的任务,如依赖性管理、资源清理等。
makefile的核心优势在于实现“自动化编译”。一旦正确配置,只需简单输入make
命令,整个工程就能自动完成编译,显著提升了开发效率,减少了人为错误,使得软件构建过程更加稳定可靠。此外,make
作为解释makefile指令的工具,已广泛集成到各种集成开发环境(ide)中,如delphi的make
,visual c++的nmake
,以及linux下gnu的make
,这表明makefile已经成为跨平台项目构建的标准实践。
总之,makefile与make
命令的结合,为软件工程提供了一种标准化、自动化的构建方案,是现代软件开发中不可或缺的一部分。掌握makefile的编写,意味着能够更好地管理和优化大型项目的构建流程,提高团队的开发效率。
依赖关系和依赖方法
在使用make/makefile前我们首先应该理解各个文件之间的依赖关系以及它们之间的依赖方法。
多文件编译
在处理包含多个源文件的工程项目时,采用多步骤的编译策略可以显著提升开发效率和构建速度。直接使用gcc
命令一次性编译所有源文件虽然可行,但在源代码频繁变更的情况下,这种做法会导致不必要的重复工作,因为哪怕只是单个源文件发生改动,也需要重新编译整个项目。
相比之下,先将每个源文件独立编译成目标文件(通常为.o
格式的二进制文件),再将这些目标文件链接生成最终的可执行程序,是一种更为高效的做法。这种方式的好处在于,当你修改了某个源文件后,只需要重新编译那个特定的源文件,生成新的目标文件,然后与其它未改动的目标文件一起进行链接,从而生成更新后的可执行程序。这样既节省了时间,又避免了资源的浪费。
需要注意的是,在编译阶段,无需显式指定头文件路径。编译器会根据源文件中的#include
指令自动查找所需的头文件。如果头文件使用的是标准库,通常使用尖括号<>
包含;如果是项目内部的自定义头文件,则使用双引号""
包含。编译器会依据不同的包含方式,从系统库路径或当前项目路径查找对应的头文件。
但是随着源文件个数的增加,我们每次重新生成可执行程序时,所需输入的gcc指令的长度与个数也会随之增加。这时我们就需要使用make和makefile了,这将大大减少我们的工作量。
步骤1: 在源文件所在目录下创建一个名为makefile/makefile的文件。
步骤2: 编写makefile文件。
makefile文件最简单的编写格式是,先写出文件的依赖关系,然后写出这些文件之间的依赖方法,依次写下去。
编写完毕makefile文件后保存退出,然后在命令行当中执行make指令便可以生成可执行程序,以及该过程产生的中间产物。
makefile文件的简写方式:
- $@:表示依赖关系中的目标文件(冒号左侧)。
- $^:表示依赖关系中的依赖文件列表(冒号右侧全部)。
- $<:表示依赖关系中的第一个依赖文件(冒号右侧第一个)。
例如以上makefile文件可以简写为:
说明: gcc/g++携带-c选项时,若不指定输出文件的文件名,则默认输出文件名为xxx.o,所以这里也可以不用指定输出文件名。
make原理
- make会在当前目录下找名字为“makefile”或“makefile”的文件。
- 如果找到,它会找文件当中的第一个目标文件,在上面的例子中,它会找到mytest这个文件,并把这个文件作为最终的目标文件。
- 如果mytest文件不存在,或是mytest所依赖的后面的test.o文件和main.o文件的文件修改时间比mytest文件新,那么它就会执行后面的依赖方法来生成mytest文件。
- 如果mytest所依赖的test.o文件不存在,那么make会在makefile文件中寻找目标为test.o文件的依赖关系,如果找到则再根据其依赖方法生成test.o文件(类似于堆栈的过程)。
- 当然,你的test.c文件和main.c文件是存在的,于是make会生成test.o文件和main.o文件,然后再用test.o文件和main.o文件生成最终的mytest文件。
- make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
- 在寻找的过程中,如果出现错误,例如最后被依赖的文件找不到,那么make就会直接退出,并报错。
项目清理
在我们每次重新生成可执行程序前,都应该将上一次生成可执行程序时生成的一系列文件进行清理,但是如果我们每次都手动执行一系列指令进行清理工作的话,未免有些麻烦,因为每次清理时执行的都是相同的清理指令,这时我们可以将项目清理的指令也加入到makefile文件当中。
即命令——“make clean”,以此来清除所有的目标文件,以便重编译。
linux第一个小程序 - 进度条
行缓冲区的概念
首先,我们来感受一下行缓冲区的存在,在linux当中以下代码的运行结果是什么样的?
对于此代码,大家应该都没问题,当然是先输出字符串hello world然后休眠3秒之后结束运行。那么对于以下代码呢?
可以看到代码中仅仅删除了字符串后面的’\n’,那么代码的运行结果还与之前相同吗?答案否定的,该代码的运行结果是:先休眠3秒,然后打印字符串hello world之后结束运行。该现象就证明了行缓冲区的存在。
显示器对应的是行刷新,即当缓冲区当中遇到’\n’或是缓冲区被写满才会被打印出来,而在第二份代码当中并没有’\n’,所以字符串hello world先被写到缓冲区当中去了,然后休眠3秒后,直到程序运行结束时才将hello world打印到显示器当中。
\r和\n
\r: 回车,使光标回到本行行首。
\n: 换行,使光标下移一格。
既然是\r是使光标回到本行行首,那么如果我们向显示器上写了一个数之后再让光标回到本行行首,然后再写一个数,不就相当于将前面一个数字覆盖了吗?
但这里有一个问题:不使用’\n’进行换行怎么将缓冲区当中数据打印出来?
这里我们可以使用fflush函数,该函数可以刷新缓冲区,即将缓冲区当中的数据刷新当显示器当中。
对此我们可以编写一个倒计时的程序。
进度条代码
gitee上传代码
首先我们需要在gitee上注册一个仓库,再将我们的仓库克隆到linux系统中,如下图所示
在linux系统上安装git工具
russleo@vm-0-2-ubuntu:~$ sudo apt install -y git
再将需要上传的目录复制到仓库目录下
再依次进行add, commit -m ,push操作
如果没有显示错误信息,我们就可以在gitee网站上看到我们所上传的文件及目录。
linux调试器 - gdb
gdb使用须知
程序发布方式:
1、debug版本:程序本身会被加入更多的调试信息,以便于进行调试。
2、release版本:不会添加任何调试信息,是不可调试的。
在linux当中gcc/g++默认生成的可执行程序是release版本的,是不可被调试的。如果想生成debug版本,就需要在使用gcc/g++生成可执行程序时加上-g选项。
对同一份源代码分别生成其release版本和debug版本的可执行程序,并通过ll指令可以看到,debug版本发布的可执行程序的大小比release版本发布的可执行程序的大小要大一点,其原因就是以debug版本发布的可执行程序当中包含了更多的调试信息。
gdb命令汇总
【进入gdb】
指令: gdb 文件名
【调试】
1)「run/r」:运行代码(启动调试)。
2)「next/n」:逐过程调试。
3)「step/s」:逐语句调试。
4)「until 行号」:跳转至指定行。
5)「finish」:执行完当前正在调用的函数后停下来(不能是主函数)。
6)「continue/c」:运行到下一个断点处。
7)「set var 变量=x」:修改变量的值为x。
【显示】
1)「list/l n」:显示从第n行开始的源代码,每次显示10行,若n未给出则默认从上次的位置往下显示.。
2)「list/l 函数名」:显示该函数的源代码。
3)「print/p 变量」:打印变量的值。
4)「print/p &变量」:打印变量的地址。
5)「print/p 表达式」:打印表达式的值,通过表达式可以修改变量的值。
6)「display 变量」:将变量加入常显示(每次停下来都显示它的值)。
7)「display &变量」:将变量的地址加入常显示。
8)「undisplay 编号」:取消指定编号变量的常显示。
9)「bt」:查看各级函数调用及参数。
10)「info/i locals」:查看当前栈帧当中局部变量的值。
【断点】
1)「break/b n」:在第n行设置断点。
2)「break/b 函数名」:在某函数体内第一行设置断点。
3)「info breakpoint/b」:查看已打断点信息。
4)「delete/d 编号」:删除指定编号的断点。
5)「disable 编号」:禁用指定编号的断点。
6)「enable 编号」:启用指定编号的断点。
【退出gdb】
1)「quit/q」:退出gdb。
发表评论