在正式开始之前我们先补充一个知识点——普通用户提权的操作。
sudo 【指令】
肯定不能自己加,得超级管理员root加——第一步:切到超级用户
。
找到sudoers文件——/etc/sudoers
第二步:编辑此文件
。
vim /etc/sudoers
第三步: 在大概一百行左右会出现这样的标志。
补充小知识:
如何显示行号呢?
:set nu
第四步:复制粘贴修改用户名即可
。
第五步:强制保存并退出
补充:因为这个文件不具备写权限
,所以得强制保存并退出。
:wq!
切换到tmp1账号再执行操作,就会看到在普通用户sudo执行whoami就会显示root的情况。
安装gcc指令
yum install -y gcc
安装g++指令
yum install -y gcc-c++ libstdc++-devel
2.直接编译生成可执行程序。
gcc test.c
这里的a.out
是默认生成的可执行程序,那有没有什么指令能改最终的可执行程序的名字呢?——重定向
gcc test.c -o test
注意:-o选项后面一定要跟目标文件,因为重定向的意思即为将文件经过处理产生的新内容重定向到另一个目标文件。
有了这个指令,之后的预处理,编译,汇编,链接就方便讲了。
我们之前的文章讲过这些内容,就不再细讲了,主要结合指令进行使用,有兴趣自行点击
查看下面的文章。
【进阶C语言】程序环境与预处理
【深度解刨C语言】预处理(全)
① 将文件执行到预处理结束就停止。
指令
gcc - E test.c -o test.i
②将文件处理到编译结束就停止。
指令
gcc -S test.c -o test.s
③将文件处理到汇编就停止。
指令
gcc -c test.c -o test.i
结果是乱码,因为vim是文本编辑器,而此文件是二进制的文件,读不出来了。
我们可以用二进制方式查看。
od test.o
结果:
虽然是二进制形式,但我还是看不懂,害~
到这里我们预处理阶段就完成了,剩下的一个阶段是链接。
我们首先要想清楚为什么要链接,也就是链接干了啥事?链接将函数的声明与函数的定义联系起来,比如库函数,头文件里面有函数的声明
,那定义
在哪呢?不就在链接时添上了么,库函数定义的地方我们称之为链接库。
链接库分为动态链接库
和静态链接库
。
公用一份代码
,虽然方便省空间,但是一旦链接库被删,那么所有的程序将无法运行!拷贝一份代码自己用
,这样虽然库删除之后会正常运行,但是会使代码的空间异常的大,通常在几十倍到几百倍
左右。gcc
yum install -y glibc-static
g++
yum install -y libstdc++-static
说明:
Linux下生成可执行程序
默认使用动态库
。
使用静态库需要后加 -static选项。
库通常在lib64目录下,以.so.数字 为后缀。
查看可执行程序所用的库——ldd 【文件】
用ll指令看生成的大小
指令
gcc test.c -g
我们先来了解一下make与makefile,make是一条指令,功能是找到makefile,并执行相应的指令
,makefile就是一个文本文件
,里面存放的是构建项目的指令,即依赖关系和依赖方法
。
当我们需要生成可执行程序时,有一大堆的源文件,不多就几百个,你是愿意每次生成一个可执行程序都用gcc命令
敲个几分钟,还是用make与makefile几秒搞定呢?答案不了了之。熟练使用这两个工具也在一定程度上提高了我们对大型项目的掌控能力
同时也提高了效率
。
答案是可以的,但限制在这几个名字“GNUmakefile”、“makefile”、“Makefile”
,而且优先级从前往后
,推荐使用“Makefile”
(比较显眼)。别的名字make可就找不到了哦!
makefile 里面主要是处理源文件与可执行程序的关系,涉及的工具就是编译器和链接器
。
下面我们就来操作一下,用的还是我们上面的代码。
① 首先我们创建一个Makefile
文本文件
② 用vim进行编辑,添加依赖关系和依赖方法
补充: 每个依赖关系的下一行必须隔一个Tab键才能写依赖方法
这样简单的就写好了!我们保存并退出用一下吧。
用法为:make 加 需要进行的操作,即 :左边的部分
,当然你也可以不写这样默认执行的就是第一条依赖关系对应的指令。
如何验证呢? 我们将项目清理一下。
直接make后面不加内容。
执行的就是我们在Makefile里面的第一个依赖关系里的指令。
我们再make一下行不行。
为啥会出现这样的内容呢?或者说这样的原理
是什么?
make指令既然说,test.exe最新的,那就有对时间的比较,跟谁比较呢?肯定是源文件的时间信息比较了。怎么看时间信息呢?
指令:stat 【文件】
只要test.exe文件修改的时间比test.c的内容更新,那就不用修改,这是咋比较呢?还记得时间戳吗?转换成时间戳比较看谁大谁小
即可。
那如果我们想要更新test.c时间呢?
指令:touch 【文件】
那如果我们不管啥时候都想make一下且成功执行呢?
那就需要关系——.PHONY : 【目标文件】
我们保存并退出多次执行make。
这样make就不管什么时候都会执行。
但是一般我们是这样的写的~
②替换——$@
用于替换:
左边的内容,$^
用于替换 :
右边的内容。
结合前面的vim 、gcc、make与makefile
我们就可以在Linux上写一个小程序了!
首先我们看一下最终版本。
首先我们看一个固定的格式,分为进度条部分,显示的进度,光标
,三个部分。
首先我们要解决的第一个问题就是——怎样让进度一直在同一行打印出来?
这里涉及两个概念——换行与回车。
这也就是说,我们在C语言的\n
和键盘上的回车键其实涉及包含两个操作,回车+换行。
那回车操作怎么表示呢?\r
还有一个概念——缓冲区。
1.在程序打开时,会默认打开三个流,默认输出流(stdout),默认输入流(stdin),默认错误流(stderr)。
2.在Linux中,缓冲区我们可以理解为一个不算太大的字符数组,当这个字符数组满时,或者程序结束,或者遇到\n等会刷新缓冲区的字符时,它会自动将内容输出并重新初始化。
3. 在Linux中,当我们需要强制进行刷新时,需要fflush函数,参数为需要刷新的流,所在头文件为stdio.h。在这里我们需要刷新的流为stdout。
那这里我们就具备了写进度条的基本能力。
我们先写一个倒计时稍微练练手。
在写程序之前我们需要将项目的框架先搭建好。
OK,我们再写一个简单的进度条。
主要功能我们在processbar.c
实现
旋转光标同理——我们可以不断覆写 - | / \
达成效果。
颜色我们这里使用的一些参数,我就在这里列出来,方便使用。
#define NONE "\033[m"//这个算是结束标志
#define RED "\033[0;32;31m"
#define LIGHT_RED "\033[1;31m"
#define GREEN "\033[0;32;32m"
#define LIGHT_GREEN "\033[1;32m"
#define BLUE "\033[0;32;34m"
#define LIGHT_BLUE "\033[1;34m"
#define DARY_GRAY "\033[1;30m"
#define CYAN "\033[0;36m"
#define LIGHT_CYAN "\033[1;36m"
#define PURPLE "\033[0;35m"
#define LIGHT_PURPLE "\033[1;35m"
#define BROWN "\033[0;33m"
#define YELLOW "\033[1;33m"
#define LIGHT_GRAY "\033[0;37m"
#define WHITE "\033[1;37m"
那如何实现闪动的效果呢?我们可以在进度为偶数时打印一种颜色,为奇数打印另外一种颜色
。
那如何将有一个箭头呢?其实在每次写入时,多写一个箭头,下次覆盖即可。
将这些功能补充,我们的代码就是这个样子的:
process.c文件
至于一些更偏向实际的用法这里就不多说了,我们目前所学涉及的就是一个回调函数。
由于Linus在维护Linux时,需要做大量的版本维护工作,为了提高效率,使用管理版本的工具迫在眉睫,前期工作得到了一家运营版本管理工具的公司的支持,但Linux维护的社区的人才过于强大,试图将此工具破解,进而想砸了这家公司的饭碗,这家公司的老板就此撤销了使用权,Linus不想再干当初的大量的活,于是便在几个星期内写了第一版开源git,并在Linux社区不断发展,因此才有了今天便捷好用的git。
如今我们在国内的网站gitee以及github,都是基于git发型的商业化版本,很像我们之前说的基于Linux内核发展而来的一些Linux操作系统。
如果在Windows上使用git,可以看此教程:
gitee(码云)的注册和代码提交【手把手】
说明:看这篇文章的前提是已经安装好git
了。
下面我们是在Linux下手把手教程。
这是我所创建的仓库。
指令
git --version
如果显示下图,说明已经安装了。
root账号
下执行如下命令。
yum install -y git
git clone 【复制的内容】
然后输入你gitee的账号和密码,这是我的
我这里把上面写好的Linux小程序,移到到本地仓库。
然后我们就开始将写好的小程序,上传到远端仓库。
执行指令①
git add .//这里的 . 的意思是将新增的内容添加到本地仓库
执行指令②
git commit -m "添加的文件的信息"//也就是说你干了啥
到这里可能会出现下面的信息。
执行指令③
git push
说明:如果版本过老,我们再在root账号下执行安装命令即可。
再看gitee上你的仓库有没上传东西,有没有小绿点,即可查看是否上传成功!
实用小操作①——查看日志信息
git log
这里是我刚上传的进度条的日志:
实用小操作②——过滤不想要的文件
为了更好的理解gdb,这里给出示例代码进行调试。
前提:先要保证自己下载好gbd。
下载指令:
yum install -y gdb
指令:
gdb 【文件】
指令:
l 【行号】
指令:
b 【行号】
指令:
info b
说明:
Num所在行,为断点的编号
。
指令:
disable 【断点的编号】
指令:
enable 【断点的编号】
指令:
r
指令:
b 【函数名】
指令:
c
指令:
n
指令:
s
说明:在一般语句下,与逐过程调试没区别,在执行函数调用语句会进入函数内部。
指令:
p 【变量名】
指令:
display 【变量名】
这里的变量最左边的数字为其编号。
undisplay 【变量的编号】
指令:
until 【行号】
指令:
bt
指令:
finish
指令:
delete breakpoints
//删除所有断点
delete breakpoint 【断点编号】
指令:
q
说明:由于这里是正在调试阶段,所以这里会询问你是否要终端调试并退出,毕竟退出后所有的断点信息都不会保存。
info(i) locals:查看当前栈帧局部变量的值
set var:修改变量的值
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
今天的分享就到这里了,如果觉得文章不错,点个赞鼓励一下吧!我们下篇文章再见
!