【Liunx】必备工具的简单使用 — yum / vim / gcc / gdb / make

📖 前言

本章将介绍Linux下常用工具的安装及使用,在Linux下安装软件,编写代码,调试代码,以及和远程gitee仓库交互等操作。


1. yum的使用

在centOS 7中安装软件:

  1. 源码安装
  2. rpm包安装
  3. yum安装

其中源码安装和rpm安装并不简单,当依赖别的库时,还需要下载其他的库,Windows是直接打包好了的。

yum安装的好处:不用编译源码,不用解决软件的依赖关系。

当我们要安装别人的软件:

  1. 需要别人先把代码给我编译成为可执行程序
  2. 需要有人将编好的软件,放在用户能下载的地方(官网,应用软件市场)

我们日常生活中就是上述的方式安装软件的,当然Liunx安装软件也是这样的。

yum类似于手机上的应用市场APP、迅雷。

在这里插入图片描述


1.1 如何下载软件:

yum list:

  • 可以显示所有可以安装软件的列表。

我们推荐先下载一下两个软件:

  • lrzsz:
  • 软件功能:支持Windows的文件传到Linux_上,直接拖拽到X-Shell。
yum list | grep lrzsz
yum install -y lrzsz.x86_64

在这里插入图片描述

  • lrzsz:
  • 软件功能:可以理解为准官方的服务器列表。
yum install -y epel-release

注意:我们下载软件要用root身份,或者通过sudo来提升权限。


1.2 配置国内yum源:

如何知道去哪台服务器上下载软件呢?

  • 因为手机应用市场内置了下载的链接。
  • Linux则是去 /etc/yum.repos.d去找对应链接。

有的时候在下载的时候会发现,下载的速度非常慢,这是因为有的yum源不是在国内,而是在国外的。这时候就需要我们配制国内的yum源了。

注意:做任何配置,绝对不要先删除,一定是先备份(就是将之前的目录改个名字)。

在这里插入图片描述
参考博客:传送门


2. vim编辑器

vim是什么?

  • 是一个编辑器
  • 类似于Windows下的记事本
  • 只有写代码的功能,并不能像vs2019那样的集成开发环境

只能用来写代码,功能强大(多模式的编辑器)。

我们为什么要学习vim?

  • 有时候,需要我们在生产环境下,需要你快速的定位问题,甚至需要你快速的修改代码!
  • vim更适合处理大型项目或者文件。

2.1 vim的安装:

有的Liunx是自带vim,有的则不是自带的,如果没有自带,需要安装一下。

yum install -y vim

2.2 vim的其中三种模式:

vim有很多中模式,我们现在学习三种模式:底行模式,命令模式,插入模式。

在这里插入图片描述
在命令模式下的一些文本批量化操作:

yy: 复制当前行,nyy复制n行
p: 粘贴再当前行的后面,np粘贴n次剪贴板的内容
dd: 剪切(删除)当前行,ndd操作n行
u: 撤销
ctrl + r: 重做
shift + g: 光标快速定位到文本末尾
gg: 光标快速移动到文本头
n + shift + g: 光标定位到文本的第n行
shift + 4: 光标定位到该行末尾
shift + 6: 光标定位到该行开头
w,b: 以单词为单位进行移动光标
h,j,k,l: 左、下、上、右
shift + `: 大小写快速切换
r: 替换光标所在处的字符,支持nr
shift + r: 批量化替换
x: 删除光标所在处的字符,nx删除n个

其他模式切换至命令模式,直接无脑Esc。

在底行模式的一些操作如下:

:w   只保存
:q   不保存退出
:wq  保存并退出
:reg 打开vim的寄存器面板
:syntax on 开启语法高亮
:set nu    显示行号
:set nonu  取消行号显示
:set tabstop=4 设置tab的缩进,默认为8
:set softtabstop=4 softtabstop是“逢8空格进1制表符”,前提是你tabstop=8
:set shiftwidth=4 设置程序自动缩进所使用的空格长度
:set autoindent 自动对齐上一行(这个选项会导致复制的时候代码排版混乱,可以考虑关闭,或者开启粘贴模式)
:set paste 开启粘贴模式
:set mouse=a 设置鼠标模式,默认是a
/+要搜索的内容  指定搜索

3. gcc / g++ 编译器

3.1 生成可执行程序的过程:

在我们之前学习中,我们讲到过如何从一个源文件形成一个可执行文件的宏观过程。今天我们用gcc每一步执行生成的文件看一看。

复习编译 + 链接:传送门

格式 gcc [选项] 要编译的文件 [选项] [目标文件]

在这里插入图片描述
预处理:

在这里插入图片描述
我们将test.i打开看一下:

在这里插入图片描述
可见:行数如此之多,很明显头文件被展开了,还有去掉注释,宏替换。

编译:

在这里插入图片描述
我们将test.s打开看一下:

在这里插入图片描述
此时我们看到的是一堆汇编代码,在这里会进行各种语法分析。

汇编:

在这里插入图片描述
我们将test.o打开看一下:
在这里插入图片描述
将汇编语言翻译成为可重定位二进制文件。
此时就是我们不认识的二进制的机器语言了,这里显示的是乱码。

此时文件就可以执行了吗,很显然并不能!
就算我们给test.o文件加上可执行权限,也不能执行。

在这里插入图片描述
因为还有一步,那就是链接!我们头文件中只是各种库函数的声明,我们还要链接其对应的库。
光有头文件是不能让代码跑起来,如果要形成可执行程序,要有头文件所对应的库。

链接:

在这里插入图片描述

此时生成的才是执行文件:

在这里插入图片描述


3.2 动静态库(认识一下):

3.2 - 1 对头文件和库的认识

如何查看头文件和库?

头文件:

ls /usr/include/

库:

ls /lib64/libc*
  • 头文件: 给我们提供了可以使用的方法,所有的开发环境,具有语法提示,本质是通过头文件帮我们搜索的!(.h结尾)
  • 库文件: 给我们提供了可以使用的方法的实现,以供链接,形成我们自己的可执行程序!(.c / .cpp结尾)

在上述生成可执行程序的过程中,在生成test.o文件的时候,我们尝试编译了一下,并没有成功,是什么原因呢?

  • 程序光有头文件是不能让代码跑起来,如果要形成可执行程序,要有头文件所对应的库。
  • 我的代码中需要的printf在哪里?
  • 我的代码中使用了printf如何和,目标printf的实现产生关联?
  • 这就是链接做的事情

链接的过程是为了让我们的代码和库的代码产生关联。

test.o链接的就是下面的这个库:

在这里插入图片描述

库分为动态库和静态库,我们先来感性的认识一下:

3.2 - 2 动态库

动态库的文件后缀: Linux(. so) windows(. dll)

自己的程序中没有实现,通过链接别人写好的库,调用别的库中的实现。

动态链接:

动态链接本质是,自己编自己的程序,只需要在链接的时候,将需要的方法和这个方法在库中的位置,通过地址的方式关联起来,这就叫动态链接。

优缺点:

  • 优点:大家共享一个库,可以节省贷源,可执行程序内部不存在重复的代码。
  • 缺点:一旦库缺失,会导致几乎所有的程序失效!

系统中很多程序都会使用C库,如果把Linux下的C库删了,那么Linux中所有的命令就跑不起来了。

3.2 - 3 静态库

静态库文件的后缀:Linux (. a) windows(. lib)

自己的程序中是将库中的相关代码,直接拷贝到自己的可执行程序中!

静态链接:

将库中所想要的方法拷贝到自己可执行的程序中,这个过程就叫做静态链接。

优缺点:

  • 优点: 不依赖任何库,程序可以独立执行。
  • 缺点: 浪费资源。

gcc中如何体现这两者的不同呢?

不同点就是他们最终形成的可执行文件体积不同。

  • 默认情况下,形成的可执行程序,就是动态链接的!

默认一般而言,都没有自带静态库,需要我们自己安装。

安装C语言静态库:

yum install -y glibc-static

安装C+ +静态库:

yum install -y libstdc++-static

ldd + 文件名可以查看程序依赖的库和程序的链接状态:

在这里插入图片描述
大小比较:

在这里插入图片描述
在这里插入图片描述
明显静态链接的要比动态链接的可执行文件大得多。

补充:

  • g++是用来编译C++程序的,用法和gcc一样
  • 因为C++是兼容C语言的,所以g++也能用来编译C语言
  • 如果部分C语言用法gcc不支持的话,那就在gcc编译的最后加上一句-std=c99
  • 例如在循环里定义变量是c99才支持的

总结:

头文件里包的是函数的声明,C语言代码必须依赖头文件和库的,因为用的头文件和各种函数全部都需要在头文件中声明,在库文件中实现,然后在编译的时候,再把你的目标文件和库文件关联起来,这时力能形成可执行程序,否则一切都是扯淡。配环境就是在装头文件,装库。


4. gdb调试

用gdb调试的时候非常麻烦比vs麻烦得多,但是在一些特定的场景下就是需要用gdb调试。

4.1 更改gdb默认的发布版本:

默认生成的可执行程序是无法调试的!因为在linux里面发布的可执行程序默认是release版本的,并不像vs2019那样发布的默认就是debug版本。

在这里插入图片描述
不过我们可以手动将其改成debug版本的:

在这里插入图片描述
这两个可执行程序运行的结果是一样的,多出来的就是调试的信息!

一段的方式读取可执行(debug):

在这里插入图片描述
而release版本却什么都没有:

在这里插入图片描述

4.2 gdb的基本指令操作:

gdb的操作:

b 行号: 打断点
info b: 查看断点
d 断点编号: 取消断点
l 行号: 显示代码
l main:显示包含main的那一行
r: run,开始运行程序,跳到第一个断点
s: step,逐语句,对应vs的F11(进入函数)
n: next,逐过程,对应vs的F10
c: continue,跳转道下一个断点
p: 查看变量
display / undisplay: 常显示 或 取消常显示
until 行号: 跳转到指定行
finish: 执行完一个函数后停下
bt: 查看函数调用堆栈

gdb知道、会用就可以了。


5. make / Makefile

经过上述的学习之后,我们知道在Linux下要是生成一个可执行文件是很麻烦的,当多个源文件一起编译的时候,一个一个生成目标文件最后再链接,麻烦死了~

项目结构:

  1. 多文件.h / .c / .cpp 先编译哪一个程序?
  2. 链接需要哪些库?
  3. 库和头文件等在哪里找?

我们在vs中生成可执行文件只需要一键点击,清理解决方案也是一键点击,非常方便。

多个源文件生成可执行,vs当中只需要点击几个按钮就可以自动生成,文件之间的关系,先编译哪个后编译哪个,哪几个文件生成可执行,一次生成几个可执行文件, vs中从来不关心。
Linux下源文件之间的关系需要我们手动维护的,说白了就是要用gcc命令。

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

  • make:是一个指令
  • Makefile/makefile:是个文件

make和Makefile类似于:vs当中生成解决方案。

我们在Makefile文件中通过,依赖关系和依赖方法,达到我们最终的目的,生成可执行程序。

  • 依赖关系:表明我为什么要生成该文件
  • 依赖方法:表明了我如何生成该文件

makefile表明的是依赖关系和依赖方法。

对应的makefile如下:
在这里插入图片描述
依赖关系:要生成process,就需要process.c
依赖方法:如何使用process.c,形成process

此时我们只要make一下就能生成可执行程序,make clean就会将可执行程序给删除了。

注意:

  • make指令默认只会形成第一个目标文件,执行该依赖关系的依赖方法。
  • 第二个依赖方法则是需要 make clean

目标文件和伪目标:都是目标文件最终目的都是要根据依赖关系执行依赖方法。

  • .PHONY:makefile语法格式中的一个关键字
  • .clean被 .PHONY 修改时,表明:总是被执行!

什么叫总是被执行:

  • 无论目标文件是否新旧,照样直接执行依赖关系!

既然有总是被执行,那么就有总不被执行:

在这里插入图片描述
当我们make过之后,再make就不会重复生成可执行程序,这就是总不被执行。

5.1 如何判断是否重新生成:

那么问题来了,makefile是如何识别我的exe/bin是新的还是旧的呢?

  • 答案就是:根据对比源文件和可执行程序的最近修改时间,评估要不要重新生成。

一般而言, Linux下的文件会有三种时间:

在这里插入图片描述

  • Access: 访问时间对于文件来说,当我们使用cat、more、less等命令读取文件内容时。
  • Modity: 对文件内容修改时,Modify、Change时间会更新。
  • Chang: 对文件属性修改时,例如chmod、chown、chcgrp等操作后,Change 时间会更新。

修改内容可能会引起Chang时间的变化,因为修改了文件内容文件的属性也会跟着变化,例如文件的大小。

Liunx内核对Access做了优化时间不变累计一定次数之后才会发生变化。

  • 因为我们会频繁的查看文件内容,一直修改文件属性的话,也会有数据被写到磁盘,造成浪费。

可执行程序和源文件对比Modify的时间来决定要不要生成新的可执行程序:

在这里插入图片描述
touch可以创建文件,也可以更新文件的时间戳:

在这里插入图片描述
此时就更新了,源文件更新,就编译这个源文件,如果可执行程序更新,就不编译。

而总是被执行则是忽略时间对比:

在这里插入图片描述

不太建议将形成的目标文,件设置成伪目标而是将清理设成为目标。

5.2 多文件的makefile:

见一见:

在这里插入图片描述

6. Linux第一个程序 —— 进度条

6.1 回车和换行的区别:

平时接触的的换行一般指的是回车 + 换行,就是另起一行。但是实际上回车和换行还是有区别的:

回车是回车,换行是换行~

  • 回车: 光标回到该行的最前面
  • 换行: 光标去到下一行,但是列不变

在我们之前学习的C语言中,\n就是回车 + 换行,而 \r 是回车。

缓冲区刷新:

  • 当我们printf一个字符串的时候,系统是先把这个字符串写入缓冲区,再把缓冲区的内容输出到屏幕上。
  • 在linux环境中,\n会自动刷新缓冲区(只要缓冲区被刷新了就会在屏幕上显示出来)。
  • 如果缓冲区没有刷新我们可以手动刷新,就需要用到fflush()函数来刷新一下。

我们通过man来看一下:

在这里插入图片描述

6.2 倒计时的实现:

有了上述知识,那么我们就可以利用这个特性实现一个简单的倒计时:

#include <stdio.h>
#include <unistd.h>

int main()
{
    int cnt = 9;

    while(cnt)
    {
        printf("%d\r", cnt);
        cnt--;
        fflush(stdout);
        sleep(1);
    }

    return 0;
}

效果图:
在这里插入图片描述

6.3 进度条的实现:

#include <stdio.h>
#include <unistd.h>
#include <string.h>

#define CNT 101
#define STYLE '#'

void process()
{
    char arr[CNT];
    memset(arr, '\0', sizeof(arr));

    const char* str = "/-|\\";
    int i = 0;

    for(i = 0; i < 100; i++)
    {
        arr[i] = STYLE;
        printf("\033[46;34m[%-100s]\033[0m [%d%%] %c\r", arr, i + 1, str[i % 4]);
        fflush(stdout);
        usleep(40000);
    }

    
    printf("\n");
}

int main()
{
    process();

    return 0;
}

效果图:

在这里插入图片描述

  • 17
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yy_上上谦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值