🌹人生最大的遗憾,就是在遗憾过去的遗憾。
目录
🏆四、Linux项目自动化构建工具-make/Makefile
🏆一、Linux软件包管理器-yum
👓1.1 什么是软件包-yum的滥觞
🌹①什么是软件包
在Windows下我们都是使用各个软件app来进行各项活动,比如想听音乐到qq音乐,看视频到爱奇艺等等。那在Linux操作系统下我们通常执行操作都是写好程序的源代码,编译,得到可执行程序。如果我们每次都要进行这样的操作未免太过繁琐。我们是否可以像在Windows下一样在软件商店下载软件,使用呢?当然可以,有人把一些软件提前编译好,做成软件包放在服务器上,通过包管理器(类似于应用商店)可以很方便的获取到这个编译好的软件包,直接进行安装。软件包和软件包管理器,就好比"App"和"应用商店"这样的关系。yum(Yellow dog Updater,Modified)是Linux下非常常用的一种包管理器,也就是应用商店。
我们知道软件包就是一个可执行程序,我们想要执行这个可执行程序,需要去相应的官网、社区去下载它的源码。而这些源码都被一些企业、厂商放在一些服务器上。所以我们下载安装软件包本质就是去远端服务器去拷贝下载一份源码,再生成可执行程序!!
那么上述的安装软件包在Linux上也是如此,比如博主使用的Centos版本的Linux就有自己的社区服务器,yum内置下载链接。相应的其他发行版本比如RedHat、Ubuntu、kail等也有自己的社区服务器和软件包管理器!
所以总结下来,yum就是一个类似于手机应用商店的软件包管理器,它里面没有下载软件的源码,只是我们联网通过yum去到相应的服务器下下载软件包的源码!
1.2 yum使用的常见指令
注意!关于yum的所有指令必须保证Linux联网!我们可以通过ping指令验证:
比如:ping www.baidu.com (随便ping一个网站)
🌹①yum install
常见使用:
普通用户:sudo yum install 软件包 or sudo yum install 软件包 -y
root用户: yum install 软件包 or yum install 软件包 -y
使用示例:
如果没有-y,yum安装时默认会询问我们是否要安装,如果加上-y,就默认安装不询问。
注意事项:
1、安装软件时需要root权限,因为需要向系统目录中写入内容,所以一般用户需要sudo提权或者到root账号下安装才能完成。
2、yum一次只能安装一个软件,正在安装一个的过程中,如果尝试再安装另一个软件,yum就会报错。
🌹②yum list
我们普通用户,并不知道要安装哪些软件,所以在Windows下访问应用商店,我们会看到很多软件。我们在Linux下就可以通过yum list指令查看软件。
我们看到yum list 会把我们当前远端服务器可供我们使用的软件全部穷举出来。然后我们看到就是上图这个样子,这些字母又是什么含义呢?博主以一个为例。
lrzsz.x86_64 0.12.20-36.el7 @base
它的架构是: 软件包名称.系统的安装包 主版本号.次版本号.源程序发行号-软件包的发行号.主机平台.cpu架构。细说一下, 软件包名称是 lrzrz, "x86_64"后缀表示 64位系统的安装包,如果是 "i686"后缀表示 32位系统安装包,选择包时要和系统匹配。"el7"表示操作系统发行版的版本, "el7"表示的是 centos7/redhat7.base表示的是"软件源"的名称,类似于"小米应用商店","华为应用商店"这样的概念。
所有包含sl关键字的软件包就都被检举了出来!!
当然,如果你觉得查看不太方便,我们也可以搭配more、less等指令来查看包含sl关键字的软件包也是可以的。(yum list | grep sl | more 或者 yum list | grep sl | less)
除了,yum list可以查看之外,我们还能通过yum search指令来查看软件。
yum search指令不但可以检举关键字,还可以列出软件包的用途。
🌹③ yum remove
和yum install 相对,yum remove是用于卸载软件的,它也需要root的权限去操作。
普通用户:sudo yum remove 软件包 or sudo yum remove 软件包 -y
root用户: yum remove 软件包 or yum remove 软件包 -y
🌹④yum 的使用示例
博主以rzsz软件包为例,演示yum的基本使用。
rzsz 用于Windows机器和远端的Linux通过xshell传输文件。安装完毕之后可以通过拖拽的方式将文件上传过去。
👓1.3yum的深层认识
我们好像并没有告诉yum去哪里下载,只是告诉yum我们要下载什么。但是yum会去yum源找下载地址。yum源是什么呢?
🌹①yum源
yum源里包含大量的下载地址,我们可以看到自己Linux上的yum源。
如果有的老铁没有安装yum源,那么我们可以配置yum源。
我们安装了Centos-7.repo, 怎么用这个yum源呢?
因为系统默认回到CentoS-Base.repo这个文件名下去寻找地址下载,所以我们只需要把它的名字:Centos-7.repo改为CentoS-Base.repo.yum在下载时就会自动到这个yum源找地址下载。
🌹②非官方软件
有些软件是没有被纳入Centos、Ubuntu、kail等相关生态平台的官方软件集合中的,称为非官方的软件集合-epel。为什么没有被纳入呢?因为它们相对于官方软件是不成熟的,比如有一定的缺陷,或者用处不大(比如之前博主举例的sl),它被当作官方软件的储备池,没有官方软件成熟。
我们可以安装一下:yum install -y epel-release
🏆二、Linux编辑器-vim
vim是一个功能强大,多模式的编辑器(编写代码)。
为什么vim是非常优秀的编辑器,博主这里简单使用一下。在vs下,我们想复制10000行代码,需要自己拷贝复制,很麻烦,但是在vim命令模式下,就很方便。
当然,vim强大之处远不止此,所以我们很有必要了解学习vim。
👓2.1vim的模式
vim 文件名 就可以进入vim查看文件
vim有很多模式,在进入vim之后 输入 help vim-modes 就可以查看有多少种模式了!
但是我们常用的也就三种模式--命令模式、插入模式、底行模式。
🌹①命令模式(Normal mode)
命令模式也叫正常模式或普通模式,是我们进入vim后默认所处的模式。命令模式下,键盘输入的所有都被当作命令看待。通常我们在命令模式下进行控制屏幕光标的移动,字符、字或行的删除,移动复制某区段及进入insert mode(插入模式)下,或者到last line mode(底行模式)。怎么退出呢? shift + : 输入wq就退出了。
🌹②插入模式(Insert mode)
一般而言,输入insert首字母i,就进入了插入模式,当然还有其他方式,后续再说。只有在Insert mode下,才可以做文字输入,按[Esc]键可回到命令模式.
🌹③底行模式(last line mode)
底行模式也叫末行模式。在底行模式下,可以进行文件的保存或退出,也可以进行文件替换,找字符串,列出行号等操作。在命令模式下,shift+: 即可进入该模式。
插入模式不能直接到底行模式。
👓2.2 vim各种模式的命令集
在了解各个模式间如何切换后,我们就要学习如何使用各个模式了。
🌹①命令模式(Normal mode)
命令模式的意义:vim是没有鼠标的时代衍生的编辑器,所以所有的操作必须由命令来操作。提高编辑效率。
Ⅰ移动光标
🖊vim可以直接用键盘上的光标来上下左右移动,正规的vim是用小写英文字母[h]、[j]、[k]、[l],分别控制光标左、下、上、右移一格。
我们看一下老式键盘就明白了,那时没有上下左右键所以当时的规定延续到了现在。
🖊按[G]:移动到文章的最后。
🖊按[$]:移动到光标所在行的"行尾"
🖊按[^]:移动到光标所在行的"行首"
🖊按[w]:光标跳到下个字的开头
🖊按[e]:光标跳到下个字的字尾
🖊按[b]:光标回到上个字的开头
🖊按[#l]:光标跳到光标后的第#个位置
🖊按[gg]:光标跳到文本开始
🖊按[CTRL]+[b]:屏幕往"后"移动一页
🖊按[CTRL]+[f]:屏幕往"前"移动一页
🖊按[CTRL]+[u]:屏幕往"后"移动半页
🖊按[CTRL]+[d]:屏幕往"前"移动半页
🖊按[#G]跳转光标到第#行。
Ⅱ删除文字
🖊[x]:每按一次,删除光标所在位置的一个字符
🖊[#x]:例如,[5x]表示删除光标所在位置的"后面(包括自己在内)"的5个字符
🖊[X]:大写的X,每按一次,删除光标所在位置的"前面"一个字符
🖊[#X]:例如,[20X]表示删除光标所在位置的"前面"20个字符(不包括自己)
🖊[dd]:删除光标所在行
🖊[#dd]:从光标所在行开始删除#行
Ⅲ复制
🖊[yw]:将光标所在之处到字尾的字符复制到缓冲区
🖊[#yw]:复制#个词到缓冲区
🖊[yy]:复制光标所在行到缓冲区
🖊[#yy]:例如,[6yy]表示拷贝从光标所在的该行"往下数"6行文字
🖊[p]:将缓冲区内的字符贴到光标所在位置。注意:所有与"y"有关的复制命令都必须与"p"配合才能完成复制和粘贴的功能
🖊[#p]:将缓冲区内的字符粘贴#次
🖊[#dd]+[p]:剪切粘贴
Ⅳ替换
🖊[r]:替换光标所在处的字符
🖊[R]:替换光标所到之处的字符,直到按下[Esc]键为止
🖊[~]:文本大小写切换
🖊[#r]:将#个字符替换成别的字符
Ⅴ撤销上一次操作
🖊[u]:撤销键,如果您误执行一个命令,可以马上按下[u],回到上一个操作。按多次[u]可以多次撤销
🖊[CTRL]+[r]:撤销的恢复
🖊[cw]:从当前光标位置开始的单词删掉,并且直接进入插入模式
🖊[c#w]:删除#个单词,并且直接进入插入模式
②插入模式(Insert mode)
🖊[i]:从命令模式切换到插入模式
🖊[o]:换行插入
🖊[a]:光标后移一位插入
🌹③底行模式(last line mode)
Ⅰ列出行号
🖊[set nu]:输入[set nu]后,会在文件中的每一行前面列出行号
Ⅱ跳到文件的某一行
🖊[#]:[#]表示一个数字,在冒号后输入一个数字,再按回车键就会跳到该行了,例如输入数字15,再回车,就会跳到文章的第15行。
Ⅲ查找字符
🖊[/关键字]:会高亮出所有的关键字,然后按[n]就会往后寻找到您要的关键字
🖊[?关键字]:光标跳转到包含关键字的那一行,再按[n]就和[/关键字]一样了
Ⅳ保存和离开vim
🖊[wq]:保存并退出
🖊[wq!]:强制保存并退出
🖊[q!]:强制退出,不保存
🖊[w!]:强制写入
Ⅵ分屏操作
🖊[vs] 文件名 创建一个文件,并分屏显示在vim上。
支持vs 创建多个文件。但是无论你分多少屏,光标只有一个,光标的意义是选中的行(编辑位置)或者屏幕。
🖊[CTRL] [ww] 切换屏幕,实现光标跨屏
注意:vim支持在不退出的情况下进行shell命令,只不过得加!新vs分屏的文件如果[wq]保存退出就会在目录内创建新文件
Ⅶ底行中的替换模式
🖊[%s/要替换的前者/后者/g]:就可以把全部的要替换的前者替换为后者。
👓2.3vim的配置原理
为什么要进行vim配置呢?如果我们不配置,我们的vim就和记事本差不多,这是很不爽的。我们在vs下写代码有语法高亮,有自动缩进,语法错误提示,而vim配置也可以使我们有这些。
vim配置文件是.vimrc文件,它是一个隐藏文件。在目录/etc/下的.vimrc文件是系统中公共的vim配置文件,如果配置了它,对所有用户都是有效的,所有用户的都会被配置。我们一般不在根目录下配置vim。通常普通用户按照自己的喜好配置自己的vim编辑器。
🌹①自己配置vim
我们可以ls -al查看一下当前用户目录下有没有.vimrc文件,如果没有,就自己创建一个。
那怎么配置呢?
我们在.vimrc文件中直接输入指令,就会在之后我们是用vim时,自动执行这个指令。
常用的vim配置还有很多:
🖊设置语法高亮:syntax.on
🖊显示行号:set nu
🖊设置缩进的空格数为#:set shiftwidth=#
关于vim的配置还有很多很多,我们可以去网上搜索一下就会出现vim配置大全。
🌹②使用插件
要配置好看好用的vim,原生的配置可能不全,我们可以选择安装插件来完善配置,保证用户是你要配置的用户,接下来:
🖊安装TagList插件,下载taglist_xx.zip,解压完成,将解压出来的doc的内容放到~/.vim/doc,将解压出来的plugin下的内容拷贝到~/.vim/plugin
🖊在~/.vimrc中添加: let Tlist_Show_One_File=1 let Tlist_Exit_OnlyWindow=1 let Tlist_Use_Right_Window=1
🖊安装文件浏览器和窗口管理器插件:WinManager
🖊下载winmanager.zip,2.X版本以上的
🖊解压winmanager.zip,将解压出来的doc的内容放到~/.vim/doc,将解压出来的plugin下的内容拷贝到~/.vim/plugin
🖊在~/.vimrc中添加let g:winManagerWindowLayout='FileExplorer|TarList nmap wm :WMToggle<cr>
🖊然后重启vim,打开~/XXX.c或~/XXX.cpp,在normal状态下输入"wm",你将看到上图的效果。
当然,这样配置显然太过麻烦,这里推荐老铁一键配置vim!
Ⅰgitee上搜索vimforcpp
找到后,下翻找到这样的:
在Linux中复制粘贴,就可以配置了
配置好之后就是这样的:
有语法高亮,有自动缩进等。
🏆三、Linux编译器-gcc/g++的使用
程序的翻译过程包括四个阶段,在C语言预处理(66条消息) C语言预处理_多睡觉才能长头发i的博客-CSDN博客时博主就介绍过编译器是如何处理代码的,这里我们通过gcc编译器的角度再来细说。
👓3.1程序的翻译过程
🌹①预处理
预处理:头文件展开,去注释,宏替换,条件编译。
示例:
🖊选项“-E”,该选项的作用是让gcc再预处理结束之后停止编译过程。
🖊选项"-o",是指目标文件,"i"文件为预处理完之后形成的临时文件。
🌹②编译(生成汇编)
🖊在这个阶段中,gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,把代码翻译成汇编语言。
🖊用户可以使用"-S"选项来生成汇编代码,该选项只进行编译而不进行汇编。
🌹③汇编
这一过程把汇编代码变成二进制目标文件,但是还是不可执行的。
🌹 ④链接(生成可执行文件obj文件)
链接就是把我们写的代码和标准库中的代码合起来。进行符号表合并,重定位。
我们可以简记ESc(也就是-E、-S、-c)是程序翻译的过程,与此同时iso(也就是-i、-s、-o)就是生成各个临时文件。
👓3.2动态链接和静态链接
🌹①静态库和动态库
我们发现我们所有使用库中函数(C标准库、C++、STL)的代码,只写了该函数的调用,并没有对应的实现。只有在我们执行到链接的时候,对应的实现才和我们的代码关联起来。而链接的过程有两种动态链接和静态链接,分别要用到动态库和静态库。
🖊静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也不需要库文件了,其后缀名一般为".a"
🖊动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库。这样可以节省系统的开销。动态库一般后缀名".so"
当然.so和.a只是Linux的命名规则,在Windows下动态库是.dll。而静态库是.lib
🐱对于动静态链接的区分好像还是不太清晰,什么意思呢?举个例子。比如我想去上网,但是我家里没有电脑,我每次上网都需要跑到网吧去上网,我们需要知道网吧在哪里,怎么去,这样我们想上网和网吧产生了关联。这就类似我们动态链接的过程,我们需要知道库在哪里,和库建立链接,找编译器,链接器。
🐕如果我家里有电脑,我就不需要去网吧,直接就能上网。我们没有和网吧产生关联。类似于我们的静态链接过程,没有和库产生关联,而是将我程序内部要用的方法,从库拷贝了一份,不在需要去库取,完成了静态链接。
🌹②动静态链接的优缺点
动态链接的优点:动态链接形成的可执行程序小,它不需要本地存库的源码,使用时链接去库里面查找。节省资源:内存、磁盘、网络。
动态链接的缺点就是库的改变会影响我们的程序,每次执行程序我们都需要去链接库,会消耗一点时间,而且如果库删除我们的程序就无法运行了!
静态链接的优势:不受库升级或者被删除的影响。
缺点是形成的可执行程序体积太大-网络,磁盘,内存。还有隐形问题就是引起其他程序时会出现相同代码出现大量重复,冗余。
👓3.3gcc的动态链接
那么我们的gcc编译器使用的是动态还是静态链接呢?
我们这里要使用file指令查看gcc编译的文件是动态还是静态链接。
我们可以看到gcc是动态链接的。那么我们动态链接依赖的库是哪一个库呢?
ldd指令可以查看我们依赖的是哪一个库。
Linux下的指令几乎都是动态链接的:
Windows下也是动态链接的。
静态链接的方式
如果我们想要静态链接,也是可以的,只不过需要加上-static
如果有的老铁无法执行生成静态链接的指令,是因为没有下载静态库。
我们需要执行这条指令:
那么这里可能有的老铁就有疑惑了,为什么动态链接不需要下载动态库?以及静态链接是拷贝库,他拷贝的是.so动态库吗?
Ⅰ静态链接占用大量空间
因为静态链接非常消耗内存,所以就被摒弃了,而我们的系统一般都会自动下载动态库而非静态库。
Ⅱ静态链接从静态库拷贝
静态链接拷贝的不是.so(动态库)内部的代码,拷贝的是静态库:/lib64/libc.a 如果没有是无法完成静态链接的。
👓3.4gcc的其他常用选项
🖊-g 生成调试信息。GNU调试器可利用该信息
🖊-shared 此选项尽量使用动态库,所以生成文件比较小,但是需要系统动态库
🖊[-O0]、[-O1]、[-O2]、[-O3]是编译器的优化选项的4个级别,[-O0]表示没有优化,[-O1]为缺省值,[-O3]优化级别最高
🖊-w 不生产任何警告信息
🖊-Wall 生成所有警告信息
🏆四、Linux项目自动化构建工具-make/Makefile
👓4.1背景
🖊会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
🖊一个工程中的源文件不计其数,按其类型、功能、模块分别放在若干个目录中,makefiel定义了一系列规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。
🖊makefile带来的好处就是---"自动化编译",一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率
🖊make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
🖊make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。
简单来说,makefile 按照我们生活里的场景就是记录完成一件事情需要哪些步骤,然后make就是执行这些步骤。
👓4.2makefile
🌹①原理
🖊规定要求文件名必须是makefile,m可以大写或不大写
🖊makefile文件里面是依赖关系和依赖方法
这里test作为目标文件,依赖于test.c文件,通过依赖方法创建。
makefile存在的意义,是为了构建项目(要做的事情):
a、表明依赖关系
b、表明依赖方法
🌹②clean
一般在makefile里面写进生成文件后,当执行完程序后我们还需要清理掉文件,在makefile里面clean表示清理。
这里clean是不依赖于任何文件的。
至此,我们可以简单写一个makefile来演示一下过程:
我们在执行clean时,需要加上make ,我们不用再敲冗长的gcc命令了!!
这里再补充一点,make只能生成一个目标文件,如果单纯的make,他只执行生成第一个文件,如果你想自己决定执行生成哪个目标文件,需要make后面加上那个方法,例如:
例如这里,如果我想生成mycode,需要make mycode
👓4.3 .PHONY
一般makefile里面的依赖方法,执行过一次也就是make过一次之后,如果没有做修改就不能再次make了。
但是我们发现,make只能一次,而clean好像不受这样的限制:
它们不同的地方除了clean不依赖关系外,另一个地方就是clean是被.PHONY修饰的。那我能不能用.PHONY来修饰我的其他依赖方法呢?
我们发现mycode依赖方法被.PHONY修饰过后,也可以多次make。那么.PHONY究竟有什么魔力使得它们可以多次make呢?
Ⅰ三个时间
不知道老铁是否还记得文件的三个时间呢?
Access time
Modify time
Change time
那这三个时间有什么用处呢?我们先对文件进行一些操作来看一下会发生什么。
修改文件的内容,三个时间都更新。修改文件,修改时间也会随之发生变化,大小变化,属性当然会变化。
我们发现,当我们修改文件的时候,文件change time和modify time发生了变化,而计算机正是根据这些变化判断文件是否发生了修改,如果发生了修改就可以再次make。如果没有,就不能再次make。
它的原理很简单:因为我们一定是先创建编写源文件,然后才有的可执行程序,所以源文件的modify time 一定早于可执行程序的modify time
如果你修改了源文件,这时候源文件的modify time就会晚于可执行程序的modify time,这时编译器认为你已经修改了,就会允许再次make
🐱如果老铁多次修改,会发现access time好像并不是我们只要访问就更新。这是因为Linux对他的更新方式进行了修改,因为如果访问的非常频繁,更改的也更加频繁,就会出现更多次的访问磁盘,对系统是一个负担。其次还因为这个时间用处不大,很少有人关注最近访问时间,所以就更改成了在一定时间内,根据我们访问的次数,次数够了再修改access time
Ⅱ.PHONY的用处
了解了三个时间,那么.PHONY的作用究竟是不要我们根据时间新旧来比较还是禁止了我们修改时间呢??(因为这两种行为都会允许我们多次make)
我们可以验证一下。这里mycode.c已经被.PHONY修饰。
我们可以看到,它的三个时间得到了更新,说明.PHONY的用处就是不让Linux去检查源文件的三个时间和可执行程序的三个时间,从而允许我们多次make。
👓4.4makefile的执行规则
🏆五、进度条
既然我们已经学习了这么多理论知识,不妨来小试牛刀,做我们Linux的第一个小程序--进度条!!
在做之前需要阐明一些问题
🌹①缓冲区问题
我们这里为什么第一个是先显现再停顿,而第二个是先停顿再显现呢?
这里就要涉及到C语言时期提及的数据缓冲区的问题。第一个因为遇到了'\n'刷新了缓冲区而把缓冲区的数据先打印了出来,所以第二个我们要刷新缓冲区fflush。
🌹②回车换行
在我们的习惯里,回车换行好像就是'\n'符号,而在原始的时候,其实
'\r'-->回车,它的作用是回到当前行的最开始
'\n'-->换行,换到下一行
解决了这两个问题,博主写了一个简单的进度条程序。
/*main.c*/
#include"process.h"
int main()
{
ProcessOn();
return 0;
}
/*process.c*/
#include"process.h"
char style[S_NUM]={'-','&','#','$','*'};
void ProcessOn()
{
int cnt=0;
char bar[NUM];
memset(bar,'\0',sizeof(bar));
const char* lable="|\\-/";
//101 times
while(cnt<=100)
{
printf("\033[42;34m[%-100s][%d%%][%c]\r\033[0m",bar,cnt,lable[cnt%4]);
fflush(stdout);
bar[cnt++]=style[N];
//sleep(1);
usleep(50000);//5s/100==0.05s == 50000 us
}
printf("\n");
}
/* process.h */
#pragma once
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#define S_NUM 5
#define NUM 101
extern void ProcessOn();//函数声明
/*Makefile*/
ProcessOn:main.c process.c
gcc -o ProcessOn main.c process.c -DN=3
.PHONY: clean
clean:
rm -rf ProcessOn
总共也就三个文件,一个Makefile。
效果还是可以的,挺好玩的。