LINUX入门篇【6】----第一个LINUX小程序---进度条及相关知识讲解

前言:

本篇我们将开始尝试构建我们的第一个LINUX的小程序----进度条作为一个十分常见的程序,在我们之后的工程实践中也是需要多次运用,但是介于我们目前还没有去学习网络等方面的知识,没法独立的去利用程序去下载一个真正的程序,自然没法根据程序去进行一个真实的下载环境,但是我们依旧可以拿出一个模拟下载的进度条程序。

1.前期预备知识讲解:

1.自动化构建代码:

让我们先想想我们在使用VS的时候的一些细节:我们只需要点击重新生成解决方案就可以直接直接重新编译我们当前的代码,而且是多个文件一起编译,但是在vim中我们对于多个文件,必须一个一个去gcc/g++,这就非常麻烦和繁琐,所以我们要寻找一种方法让我们的vim编译器也可以做到只需要一次指令就可以同时将多个文件一起编译,在这里,我便要引入我们的make和makefile.
首先,make是指令,而makefile是我们需要创建的一个不能改变名字的一个文件,你可以这样理解makefile:它是一个在当前目录下存在的一个具有特定格式的文本文件。
我们首先要创建一个makefile文件,注意,我们创建的时候名字必须是Makefile/makefile这两个,大小写没影响,但是名字不能变,如下:
在这里插入图片描述
有了这个文件,我们就可以使用make指令来自动执行makefile文件里面的命令了。

依赖方法与依赖关系:

我们的makefile文件里面命令的本质实际上就是两个:依赖方法和依赖关系,我们代码之间主要是依靠一个一个文件来封存,所以本质上文件之间的关系就反映着代码之间的关系,如下:
在这里插入图片描述
在这里,我写好了main.c process.c process.h三个文件,其中两个源文件,一个头文件,我们在书写C语言的程序的时候就知道,我们都是直接将源文件进行编译成可执行程序的,又根据我们前面程序的翻译中知道,我们的头文件是以链接的形式直接拷贝或者地址链接到程序中的,所以我们不需要对其进行编译展开,由上述的逻辑,我们大致构建出了一个文件之间的依赖关系:
main.c process.c两个文件要被编译成一个可执行程序文件,而头文件是链接进行的,由此,我们的可执行程序文件与两个源文件就是依赖关系,而他们的依赖方法就是将这两个源文件编译成一个可执行程序,头文件自己链接,由此,我们可以这样去写我们的Makefile的指令:
在这里插入图片描述
第一行是依赖关系,指的是我们的关系是process可执行程序和我们的两个源文件之间的关系,第二行需要先TAB空格后开始写,主要写依赖方法:在这里我们的$^代表的是冒号之后的依赖的对象,而 $@代表的是冒号之前的依赖对象,当然你直接写名字也是可以的,主要是这样写更加简便,然后这条指令我不多说,就是上篇文章我们说过的编译指令,后面的@ echo(注意这里@和echo之间要留有空格,否则这条指令执行会全是乱码,不简洁),这条指令就是将双引号里面的内容呈现到屏幕上,这个指令我们之前也学到过,它同样可以将对应的字符输入到文件中。
由此,我们的编译指令便构建了出来,现在只需要我们输入make,就可以自动编译代码成为可执行程序,如下:
在这里插入图片描述
这样当我们去查看我们的目录,一个process可执行程序便出现在了列表中,这便是我们的可执行程序。
但是,一个程序光可以编译是不够的,我们还需要它进行程序的清理,也就是要自动删除我们的全部程序文件,跟gcc/g++一样,倘若一个一个删就会太麻烦,所以我们同样使用利用程序将其一次清理指令全部执行的命令,即我们需要使用.PHONY伪代码来进行,这是由于我们的删除文件是没有依赖对象的,删除不需要跟其他文件搭建关系,但是我们的依赖关系如果不建立,依赖方法又是没法执行的,故我们通过使用伪代码来解决这个问题,.PHONY的特点在于:
.PHONY没有依赖关系这么一说,它会直接执行对应的依赖方法,即无论目标对象是否存在都会重新生成,不会在于文件新旧的问题,这是因为目标对象与其同名文件之间没有一定必要的相互关系。
故在这里我们可以这样总结:
.PHONY修饰的文件本身是和普通文件没有明显去别的,它只是总是被执行它对应的依赖方法,并且这种执行是强制性的。
由此,我们可以这样接着编译指令构建我们的删除指令,如下:
在这里插入图片描述

在这里,我们的clean即我们的对象,我们执行的指令当输入这个对象的时候,即当我们输入make clean的时候,我们就会去执行清理可执行程序process的指令rm -f,这样,我们就可以自动去清理多个程序文件,而不需要一个一个去清理了,如下:
在这里插入图片描述

make/makefile的自主推导性:

对于下面的代码:

mybin:code.o
 gcc code.o -o mybin
code.o:code.s
 gcc -c code.s -o code.o
code.s:code.i 
 gcc -S code.i -o code.s
code.i:code.c
 gcc -E code.c -o code.i  

此代码是可以执行的,虽然扫描文件的时候从上到下执行,但是由于makefile的自主推导性,它是这样去分析这些代码的:
从尾部向上依次按照文件的编译过程去找是否存在对应的文件,知道形成可执行程序,所以,我们的文件是不怕顺序问题的,主要是该有的逻辑我们是不能有缺失的,否则会影响程序的编译。
在这里插入图片描述

2.ACM时间与通过时间对文件新旧的判断:

我们倘若已经生成了一个process可执行文件,我们要是再次对其编译可以么?
倘若我们这样去执行,就会跳出这样的回应:
在这里插入图片描述
这条指令的意思就是说,文件已经更新到最新版本时间,不支持再次编译了,也就是说,此时文件是旧的,LINUX是可以分辨出来并且拒绝重复编译的,那么,LINUX是如何去区分一个文件是否被修改从而确定其是否可以重新编译的呢?
这就不得不提到我们的ACM时间了。
何为ACM时间呢?让我们stat任意一个文件来查看文件的详细信息,如下:
在这里插入图片描述
你会发现,有三个时间:
Access:读写访问时间,当我们打开文件读取内容时,就会修改这个时间
Modify:文件内容修改时间,当我们进入文件并修改文件内容时,就会修改这个时间
Change:文件属性修改时间,文件的属性基本随着内容的修改也在不断的被修改着

根据他们三个之间的特点,他们相应的关系如下:
ACM分别对应着三个时间的首字母,当C时间被修改时(比如文件的三个读写权限)它只会影响自己,另外两个时间不被修改,当我们去修改M时间时,则A时间和C时间都会由此而被改变,而修改A时间时,对应的C文件的属性也会被修改。
那,文件访问的本质是什么呢?
首先文件是被存储在磁盘上的,也就是说,访问文件本质上就是访问磁盘,这个过程的效率是很低的,很耗费时间,会影响我们程序的执行。由此,在LINUX中,我们是不会重复去编译文件的,因为LINUX有着庞大的文件,倘若依次修改磁盘,会导致出现大量的磁盘的IO操作,这严重影响了系统的效率给,故LINUX会尽可能的减少文件的修改次数。
所以回过来,我们的文件的新旧是如何被系统分辨出来的呢?
它主要依靠的实际上就是文件的修改时间,但是时间并非本质,通过时间对比出来的新旧才为本质,源文件通过与可执行文件的修改时间进行对比:
首先第一次的时候,我们一定是先有源文件,然后通过编译得到可执行程序,此时我们会得出结论,源文件的修改时间一定是小于可执行程序文件的修改时间的,然后从第二次开始,到后面之后的很多次修改,我们修改文件的时候,先去修改源文件,此时当我们再去编译的时候,此时的源文件的修改时间反而大于可执行程序的修改时间了,故此时两者的大小关系发生了变化,LINUX系统识别到了这种变化,意识到文件做出了修改,故此时认为文件为新,执行重新编译的指令,但旧文件就不会执行这个指令,由此,便通过源文件和可执行文件的修改时间的大小关系的变化去分辨新旧文件。
但是,这条规律在大部分情况下都没问题,问题的产生不仅仅是修改新文件就能解决的,有些历史问题,需要重新清理项目才可以解决。
那如何修改文件的时间呢?
我们有时对代码已经足够完美了,没必要修改的情况下,我们还想让其重新编译,这时我们就需要去更新我们的3个时间去让文件变成新的,这里我们就需要我们的touch指令来修改文件的时间戳:
touch -a/-c/-m:分别对应更新a,c,m三个时间,倘若不加,就是对整体的文件的三个时间进行更新。
在这里要补充一下:对于.PHONY的伪目标,它是无视时间的,只要调用就必定执行,没有新旧判断这一说。

好了,现在我们已经掌握了vim编译器软件,gcc/g++编译代码,自动化构建代码,我们接下来就开始正式进行我们的进度条小程序的书写。

2.进度条程序:

说到进度条,我在这里以LOL的进度条举例子,在我们进入LOL游戏之前的10人英雄界面,我们就有一个进度条和一个不断旋转的小圆圈,入下:
在这里插入图片描述

由于实在找不到旋转的图标了,但是我们大致看到右下角的这个进度数字标识,再加上我们的进度条和一个360度旋转的小光标,这便是我们整个进度条程序的全部组成部分,如下:
在这里插入图片描述
好了,大致的铺垫都完事了,现在让我们开始正式书写程序。

1.缓冲区:

在LINUX中提供了一个接口头文件<unistd.h>,通过它可以让我们使用sleep函数,让程序休眠一段时间(秒数),首先我们要明白,在C/C++语言中,针对标准输出,给我们提供了默认的缓冲区,主要是输出缓冲区,在stdout开启的同时stdin,stdeer也会随着stdout一同开启。
所以,本质上我们打印的本质是先将要打印的内容放到stdout的输出缓冲区中,然后立刻刷新输出缓冲区打印出内容,倘若我们延时sleep前刷新stdout,我们就会立刻打印出内容,而不是等了几秒才打印,而我们平时使用的换行符\n实际上也是一种强制刷新的方式,所以我们回车每次都可以强制刷新缓冲区。
C/C++为我们提供了fflush()函数来强制刷新缓冲区,利用它我们就可以不断刷新缓冲区从而实现动态进行程序的效果

2.回车换行:

注意,回车和换行是两个完全不同的概念,你可以去看我们的键盘。我们所谓的回车键是这样的:
在这里插入图片描述
注意一个细节,这里的回车键先向下再向左,但我们实际上的回车就是直接回到最左边,所以我们键盘上实际的回车键是先向下再回车而不是单纯回车的意思,这个不要理解错了。所以,为什么我们在程序输入的时候Enter会直接跳到下一行的最开始而不是直接下一行,这正是因为这个键位是回车加换行的意思,两个命令同时触发了,**在C语言中,换行就是‘\n’,而回车就是’\r’.**故倘若我们向让我们的光标一直停在一个位置开头,就每一次都回车一次让光标一直在最左边的开头位置即可。
同时注意,我们其实每一个向屏幕输入的数字也好,字母也好,各种符号也好,他们的本质都是以字符形式被识别和存储的,而根据我们占位符的不同去识别和理解这个字符对应的数据到底是什么,所以这才有ASCII表的存在,就是为了转化字符的。

程序代码如下:

有了上面的知识的铺垫,我们的进度条自然而然就出来了,代码如下:
process.c文件(函数文件)
本来是想给源码的,但是太麻烦了,就直接上图片了,抱歉~~~~~!!!
在这里插入图片描述
这个就是我们的函数代码,我称之为进度条最终版本,在这个版本里,我们主要要实现一个进度条配合程序实时的跟进,而不是进度条只是自己向后运行而不考虑实际的下载情况,所以我在这里采取的是传入比率的方式带入程序进行运算,我在这里定义了一个静态数组和一个静态的整型,其中静态数组是保证进度条一直向前进行的,由于我们的进度条是函数形式,出了函数进度条的数组就会被销毁(当然,倘若你定义一个全局变量的数组也可以),同时,为了保证我们的进度条加载卡住的时候我们的小光标依旧在选旋转,我们的这个整型变量配合上一个字符数组来保证我们小光标的实时更新,以告诉用户我们还在加载而不是卡住了,打印的过程中的那个\033[31;44是我加上的输出的字符的颜色和背景色,这个上网就能查到,注意看我fflush的位置,我是先让打印结果进入缓存区后,再刷新,这样就起到了在我主函数的延时之前先刷新字符串打印出我们的进度条。
在最后加载完成的时候,补上加载完成的提示语句,此时rate为100%,即为进度条加载完毕。
process.h文件(头文件)
在这里插入图片描述
main.c文件(主函数文件)
在这里插入图片描述
我们在这里配合着我们的头文件一起看主函数文件,头文件不多说,其实主函数文件也没什么说的,基本的代码大家都能看懂,但是在这里我想说一说,我们的进度条一般是作为回调函数来调用使用的,而不是直接放入程序内部,因为这个进度条可能需要实时更新,所以我们定义了一个函数指针并将其类型重定义为callback_t ,传入我们的加载download函数中为cb,配合着cb,这样,我们只需要传入我们每次想要使用的任意版本的进度条即可,这种方法效率很高,同时也很节省时间。usleep保证了时间的进一步缩小为毫秒为单位,更加接近真实的时间而不是sleep的慢速,同时我们还模拟了一个进度条卡住的情况,当rate大于百分之50的时候,由于total被限制为target的一半,故我们的rate也被限制在百分之50,从而就模拟了进度条卡住的情况。
通过这样写,我们的最终效果如下:
在这里插入图片描述
虽然很简陋,但是你依旧可以通过一些方式进一步优化这个建议的进度条**,不过在我看来,最重要的是一些我们缓冲区,延时函数,如何操作LINUX熟练的写程序,进度条为何利用回调函数来进行等等这些重要的知识才最为关键**

总结:

无论如何,我们的进度条代码算是完成了,这是我们的第一个LINUX的小程序,但不会是最后一个,写下了这个小程序,让我们更加熟练的使用LINUX去写代码,这才是我们的关键所在,学习LINUX不仅仅是会写代码,同时要对整个生态,系统的一些很多知识有更多的理解和新的感受,这才是最关键的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/160051.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Humanoid Robotics Whole Body Control(WBC)全身控制

系列文章目录 文章目录 系列文章目录前言一、ROS —— 什么是全身控制&#xff1f;二、IEEE - RAS三、维也纳工业大学 —— 自动化与控制研究所&#xff08;ACIN&#xff09;四、IIt&#xff08;意大利技术研究院&#xff09; 前言 谷歌的几种解释 一、ROS —— 什么是全身控制…

PPT基础入门

目录 相关设置快捷键shift 快捷键Ctrl 快捷键Ctrl Shift 组合快捷键快捷键总结 相关设置 设置撤回次数 自动保存 图片压缩 字体嵌入&#xff1a;目的是在不同的电脑上保留已经设置好的字体 多格式导出 &#xff08;1&#xff09;可以导出PDF &#xff08;2&#xff09;可以导…

简单线性回归函数

简单线性回归函数 定义术语理解简单线性回归例子 定义 线性回归&#xff1a;利用线性回归方程中最小平方函数对一个或多个自变量和因变量之间关系进行建模的一个回归分析。该建模的目标为找到各个系数的最佳值让预测误差最小 简单线性回归&#xff1a;只有一个自变量的线性回…

2023.11.18 每日一题(AI自生成应用)【C++】【Python】【Java】【Go】 动态路径分析

目录 一、编程挑战&#xff1a;动态时间序列分析 实际应用&#xff1a; 实现提示&#xff1a; 二、实现 1. C 2. Python 3. JAVA 4. Go 一、编程挑战&#xff1a;动态时间序列分析 问题描述&#xff1a; 假设你是一名软件工程师&#xff0c;需要开发一个应用来分析和预…

贝茄莱BR AS实时数据采集功能

实时数据采集功能在PLC系统调试过程中&#xff0c;有助于调试人员对变量变化进行监测&#xff0c;通过波形对比&#xff0c;反应不同变量间的相互作用。该测试目的在于验证贝加莱系统组态软件的实时数据采集功能。 贝加莱系统组态软件提供Trace功能&#xff0c;连接PLC&#x…

如何在远程协同视频会议中确保安全性?

随着远程工作的普及&#xff0c;远程协同视频会议已成为企业和团队之间进行交流和协作的重要工具。与此同时&#xff0c;会议中的安全性问题也日益凸显。本文将介绍如何在远程协同视频会议中确保安全性&#xff0c;主要包括以下方面&#xff1a; 1、内网部署 将会议服务器部署…

基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(五)

公共字段自动填充 1.1 问题分析1.2 实现思路1.3 代码开发1.3.1 步骤一1.3.2 步骤二1.3.3 步骤三 1.4 功能测试 1.1 问题分析 在前面我们已经完成了后台系统的员工管理功能和菜品分类功能的开发&#xff0c;在新增员工或者新增菜品分类时需要设置创建时间、创建人、修改时间、修…

【开源】基于Vue和SpringBoot的婚恋交友网站

项目编号&#xff1a; S 057 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S057&#xff0c;文末获取源码。} 项目编号&#xff1a;S057&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 会员管理模块2.3 新…

腾讯云轻量4核8G12M带宽服务器租用价格和S5实例报价

腾讯云4核8G服务器优惠价格表&#xff0c;云服务器CVM标准型S5实例4核8G配置价格15个月1437.3元&#xff0c;5年6490.44元&#xff0c;轻量应用服务器4核8G12M带宽一年446元、529元15个月&#xff0c;阿腾云atengyun.com分享腾讯云4核8G服务器详细配置、优惠价格及限制条件&…

llvm源码windows编译

1.克隆llvm源码: git clone --config core.autocrlf=false https://github.com/llvm/llvm-project.git 2.创建build文件夹并生成makefile 生成前置条件: cmake ,ninja,python3要先安装 cmake -S llvm -B build -G Ninja -DCMAKE_BUILD_TYPE=Release 生成成功 3.编译 进…

场景交互与场景漫游-场景漫游器(6)

场景漫游 在浏览整个三维场景时&#xff0c;矩阵变换是非常关键的&#xff0c;通过适当的矩阵变换可以获得各种移动或者渲染效果。因此&#xff0c;在编写自己的场景漫游操作器时&#xff0c;如何作出符合逻辑的矩阵操作器是非常重要的&#xff0c;但这对初学者来说还是有一定难…

Flutter笔记:桌面端应用多窗口管理方案

Flutter笔记 桌面端应用多窗口管理方案 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/134468587 【简介…

Excel 文件比较工具 xlCompare 11.01 Crack

比较两个 Excel 文件之间的差异 xlCompare. xlCompare.com 是性能最佳的 Excel diff 工具&#xff0c;用于比较两个 Excel 文件或工作表并在线突出显示差异。xlCompare 包括免费的在线 Excel 和 CSV 文件比较服务以及用于比较和合并 Excel 文件的强大桌面工具。如果您想在线了…

C语言每日一题(32)环形链表

力扣网 141.环形链表 题目描述 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数 pos 来表示链表尾…

2024年山东省职业院校技能大赛中职组 “网络安全”赛项竞赛试题-C卷

2024年山东省职业院校技能大赛中职组 “网络安全”赛项竞赛试题-C卷 2024年山东省职业院校技能大赛中职组 “网络安全”赛项竞赛试题-C卷A模块基础设施设置/安全加固&#xff08;200分&#xff09;A-1&#xff1a;登录安全加固&#xff08;Windows, Linux&#xff09;A-2&#…

聚观早报 |零跑C10亮相广州车展;小鹏X9亮相广州车展

【聚观365】11月18日消息 零跑C10亮相广州车展 小鹏X9亮相广州车展 坦克700 Hi4-T开启预售 超A级家轿五菱星光正式预售 哪吒汽车发布山海平台2.0 零跑C10亮相广州车展 零跑汽车首款全球车型C10在广州车展首次亮相&#xff0c;同时该车也是零跑LEAP 3.0技术架构下的首款全…

asp.net 学校资源信息管理系统VS开发sqlserver数据库web结构c#编程计算机网页项目

一、源码特点 asp.net 学校资源信息管理系统 是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 asp.net学校资源管理系统 二、功能介绍 本系统使用Microsoft Visual Studio 2019为开发工具&#xff0c;SQL …

小米真无线耳机 Air 2s产品蓝牙配对ubuntu20.04 笔记本电脑

小米真无线耳机 Air 2s产品蓝牙配对ubuntu20.04 笔记本电脑 1.我的笔记本是 22款联想拯救者y9000k&#xff0c;安装了双系统&#xff0c;ubuntu20.04。 2.打开耳机&#xff0c;按压侧面按钮2秒&#xff0c;指示灯显示白色闪烁。 3.打开ubunru20.04 系统右上角wifi的位置&…

C++菜鸟日记2

关于getline()函数&#xff0c;在char和string输入的区别 参考博客 1.在char中的使用&#xff1a; 2.在string中的使用&#xff1a; 关于char字符数组拼接和string字符串拼接方法 参考博客 字符串拼接方法&#xff1a; 1.直接用 号 2.利用append&#xff08;&#xff0…

Jmeter 如何监控目标服务的系统资源

下载Jmeter插件管理下载 perfmon 将这个插件管理放到Jmeter的\lib\ext目录下 然后重启Jmeter jmeter-plugins-manager-1.10.jar 下载 perfmon插件 添加 io 内存 磁盘的监听 并且添加监听 在宿主机中安装代理监听程序 并启动 ServerAgent.tar.gz