linux工具:软件包管理器yum|编辑器vim|编译器gcc/g++|调试器gdb|自动化构建工具make/makefile|linux小程序:进度条|git命令行(代码片段)

跳动的bit 跳动的bit     2022-10-22     443

关键词:

文章目录

【写在前面】

我们学习 Linux 主要是在上面做开发的 —— 写代码、编译代码、调试代码、自动化构建项目、上传 github/gitee。在这里我们一共会介绍 5 - 6 个工具 —— 软件包管理器 yum、文本编译器 vim、代码编译器 gcc/g++、调试器 gdb、自动化构建项目 make/Makefile、以及 Linux 上的 git 的命令行。

一、Linux软件包管理器yum

💦 什么是软件包

  • 在 Linux 下安装软件,一个通常的办法是下载到程序的源代码,进行编译,得到可执行程序
  • 但是这样太麻烦了,于是有些人把一些常用的软件编译好,做成软件包(可以理解成 windows 上的安装程序)放在服务器上,通过包管理器可以很方便的获取到这个编译好的软件包,直接进行安装
  • 软件包和软件包管理器,就好比 ”APP" 和 “应用商店” 这样的关系
  • yum(Yellow dog Updater, Modified)是 Linux 下非常常用的一种包管理器,主要应用在 Fedora、RedHat、Centos 等发行版上,yum 除了查找、安装、卸载,还可以解决依赖关系,后面再说

💦 如何安装软件

通过 yum 我们可以通过一条很简单的命令安装 lrzsz

sudo yum install -y lrzsz

-y 表示有关于这次安装的问题不用请求我的同意,出现 “complete" 字样,说明安装完成。

⚠ 注意

  • 安装软件时由于需要向系统目录中写入内容,一般需要 sudo 或者切换到 root 帐户下才能完成
  • yum 安装软件只能一个装完了再装另一个,正在 yum 安装一个软件的过程中,如果再尝试 yum 安装另一个软件,yum 会报错
  • 如果 yum 报错,请自行百度

💦 如何卸载软件

仍然是一条命令:

sudo yum remove -y lrzsz

-y 表示有关于这次卸载的问题不用请求我的同意,出现 “complete" 字样,说明卸载完成。

💦 关于rz sz

这个工具用于 windows 机器和远端的 Linux 机器通过 xshell 传输文件,安装完毕之后输入 rz 命令后可以通过拖拽的方式将文件上传。

sz 则相反。

💦 注意事项

  1. 关于 yum 的所有操作必须保证主机(虚拟机)网络畅通,可以通过 ping 指令验证(当然云服务器的话就可忽略了)

ping www.baidu.com

  1. yum 不能同时跑一台机器

💦 查看软件包

通过 yum list 命令可以罗列出当前一共有哪些软件包,由于包的数目可能非常多,我们可以使用 grep 命令筛选到我们关注的包。

yum list | grep lrzsz

结果如下:

说明:

  • lrzsz.x86_64:软件包的名称和适合的版本
  • 0.12.20-36.el7:el7 表示操作系统发行版本 —— Centos7、RedHat7
  • @base:通常指的是这个软件的提供者是谁;
    epel 指的是它的发布发属于扩展源,对于源,稍后会说明

我们可以筛选出 sl 命令,它就属于扩展源:

这里安装 sl 命令后运行 sl 命令就可以看到小火车了:

Centos 7 好玩的命令:用于练手

yum 源 ❓

在这里要提一句,有很多同学玩的是虚拟机,有可能默认带的 yum 源是不满足需求的(国外的或老版本的),这时就需要手动的去更新 yum 源,yum 要安装软件,那么它是怎么知道要去哪个地方找呢 ???

这里 yum 源是在 etc 路径下:

yum.conf 是 yum 的主配置,这个文件尽量不要变换:

可以看到这里的 yum 源,而我们需要改的是 CentOS-Base.repo:

此时我们 vim CentOS-Base.repo,这里已经配置过了 —— 阿里云的服务

其中可以看到很多链接,说人话就是有了这个配置后,当你 yum 时,它会根据你的配置去找,这里我们也可以去复制链接去浏览器试试(注意这里有些链接可能失效了):

说了这么多,我们就来配置一下(这里可以直接百度 Centos 7 更新 yum 源):

  1. 备份

cd /etc/yum.repos.d/
mkdir repo_bak
mv *.repo repo_bak/

  1. 下载新的 CentOS-Base.repo 到 /etc/yum.repos.d/

wget http://mirrors.aliyun.com/repo/Centos-7.repo

  1. yum chean all 清除缓存,运行 yum makecache 生成新的缓存

yum clean all
yum makecache

  1. 安装 EPEL(Extra Packages for Enterprise Linux) 扩展源

yum install -y epel-release

  1. 再次运行 yum clean all 清除缓存,运行 yum makecache 生成新的缓存,查看启用的 yum 源和所有的 yum 源

yum repolist enabled
yum repolist all

  1. 更新 yum

yum -y update

扩展源 ❓

CentOS-Epel.repo 就是扩展源,它一般默认是没有的,像 Base 这种 yum 源对软件的要求就是稳定、可靠、来源明确,但是这样软件更新的速度就比较慢,所以有很多软件都已经开发出来了,这些软件就放在 Epel 中,这里 Base 就像应用商城,Epel 就像浏览器。

二、Linux开发工具

在此之前,别人问你:

🧓🏿你在什么环境下写代码 ?
🧑🏿Visual Studio 2017。

🧓🏿你在什么环境下调试代码?
🧑🏿Visual Studio 2017。

🧓🏿你在什么环境下编译、链接代码?
🧑🏿Visual Studio 2017。

对于上面这种环境,我们称之为集成开发环境。相比我们在 Linux 中大部分情况下我们所使用的工具都是独立的工具 —— 比如我们写代码用 vim、编译用 gcc/g++、调试用 gdb、维护项目关系用 make/Makefile 等。对于这些工具的安装和卸载这里就不多说了,主要讲解它们的使用。

三、Linux编辑器 —— vim的使用

vi/vim 的区别简单说,它们都是多模式编辑器,不同的是 vim 是 vi 的升级版本,它不仅兼容 vi 的所有指令,而且还有一些新特性。例如语法高亮,可视化操作不仅可以在终端运行,也可以运行于 x window、 mac os、windows,所以这里我们学习 vim。事实上 vim 并不好学,成本较高,那为啥还要学习 vim 呢 ?—— 主要原因有两个:其一是 vim 用的比较广泛,当然其功能也是很强大,大成后可以完全摆脱鼠标的束缚;其二是基本所有的 Linux 机器上都默认带有 vim 的,可以这么说,vim 只要熟练了,其它的文本编译器都不足为惧。vim 和 make/Makefile 使用的熟练度是衡量一个 Linux 程序员水平的一个很重要的东西。

1、vim的基本概念

vim 共有 12 种模式:six BASIC modes 和 six ADDITIONAL modes。其中我们目前只学掌握 3 种即可,分别是命令模式(Command mode)、插入模式(Insert mode)、底行模式(last line mode),各模式的功能如下:

  1. 正常/普通/命令模式(Normal mode)
    控制屏幕光标的移动,字符、字或行的删除,移动复制某区段及进入 Insert mode 下,或者到 last line mode。
  2. 插入模式(Insert mode)
    只有在 Inert mode 下,才可以输入,按【Esc】键可回到命令行模式,该模式是我们后面用的最频繁的编辑模式。
  3. 底行/末行模式(last line mode)
    文件保存或退出,也可以进行文件替换,找字符串,列出行号等操作。在命令模式下,shift + : 即可进入该模式。如若要查看你的所有模式:打开 vim,底行模式直接输入 :help vim-modes。

2、vim的基本操作

  1. 进入 vim,在系统提示符号输入 vim 及文件名后,就进入 vim 编辑器

    $ vim test.c
    需要注意的是,进入 vim 后,默认处于【命令模式】,需要切换到【插入模式】才能编辑

  2. 【命令模式】切换至【插入模式】

    输入 a 或 i 或 o

  3. 【插入模式】切换至【命令模式】

    【Esc】即可转到【命令模式】

  4. 【命令模式】切换至【末行模式】

    【shift + :】

  5. 退出 vim 及保存文件,在【命令模式】下,按【:】进入【末行模式】

    :w (保存当前文件)
    :wq (存盘并退出 vim)
    : q! (不存盘强制退出 vim)


如果你在 vim 时,网络突然断线了,此时 vim 会自动帮你保存的,你可以输入下面的选项,如 R 把它恢复出来,保存并退出,但是每次打开时它都如上图提示。怎么解决呢 ?—— 可以先看下面的选项有无 D,如果有,直接 D,否则复制上图的倒数第二行中引号内的内容,出去 rm 即可。

⚠ 注意


一般底行模式和插入模式的切换需要先转至命令模式才能切换。如果将来你不知道你在哪种模式下,比如【REPLACE 替换模式】,可以直接无脑【Esc】直接回到命令模式。

3、vim正常模式命令集

1. 进入插入模式/底行模式

按【i】切换进入插入模式后,是从光标当前位置开始输入文字
按【a】进入插入模式后,是从目前光标所在位置的下一个位置开始输入文字
按【o】进入插入模式后,是插入新的一行,从行首开始输入文字
按【:】进入底行模式

2. 移动光标

上图中绿色的小方块就是我们光标所在的位置,我们可以使用 ⬆ ⬇ ⬅ ➡ 方向键进行移动定位,在 vim 中与之对应的是 h(左) j(下) k(上) l(右) 键(注意只有小写状态下才生效),一般我们最常用的也是这个,当然你要用也没人拦着你。

hjkl 是按字符为单位移动,有时效率较低,所以 vim 中的 w、b 是按单词为单位进行移动(b 是反向)。

比如有人写了一个又臭又长的代码,我想给它删掉,可以【$】直接定位到行尾,相反【^】可以直接定位到行头。如果有上千行的代码可以【G/shift+g】(shifg+g 就是 G)直接定位到最后一行,相反【gg】可以直接定位到第一行。如果想定位到中间如 666 行,先输入 666 后,再【G/shift+g】。

注意这里不仅仅只有这些移动方式,这里只是最基础光标定位操作,其余的罗列在下面。

为啥 vim 使用 hjkl 移动光标 ❓

这是有一定的历史渊源的,当 Bill Joy 开发 Vi 文本编辑器时,他使用的机器机器是 ADM-3A 终端机,这台机器并没有方向键,所以把 HJKL 键作为方向键。当然现如今我们仍然使用 HJKL 的原因是它的使用效率并不比方向键低,其次还有一个关键原因是买键盘可以不用买 104 键了,也不用买 87 键了,直接买 74 键 —— 嗯,算下来划算了不少,携带又方便。当然并不是这个原因啦,其实在有些场景下必须得使用 HJKL,比如 vim 下的批量注释使用方向键是不行的,所以那些想减少学习成本的同学还是老老实实的练吧。

⚠ 注意以下命令都需要区分大小写,G 命令可以用 shift + g 来代替。

【h/j/k/l】vim 可以直接用键盘上的方向键来上下左右移动,但正规的 vim 是用小写英文字母 h/j/k/l
【$】: 移动到光标所在行的结尾
【^】: 移动到光标所在行的行首
【w】:光标跳到下个字的开头
【e】:光标跳到下个字的结尾
【b】:光标回到上个字的开头
【G/shift+g】:进入文本末端
【gg】:进入文本开始
【# + G/shift+g】:光标移到该行的第 # 个位置
【ctrl+b】:屏幕往后移动一页
【ctrl+f】:屏幕往前移动一页
【ctrl+u】:屏幕往后移动半页
【ctrl+d】:屏幕往前移动半页

3. 复制粘贴

【yw】:将光标所在之处到字尾(单词)的字符复制到缓冲区
【#yw】:复制 # 个字符到缓冲区
【yy】:复制光标所在行到缓冲区
【#yy】:例如 【6yy】表示拷贝从光标所在的该行往下数的 6 行文字到缓冲区
【(#)p】:将缓冲区内的字符贴到光标所在位置,如果要粘贴到 100 份,可在 p 之前指定,比如 100+p,注意所有与 y 相关的复制命令都必须与 p 配合才能完成复制与粘贴功能

4. 删除剪切

注意以下的删除都相当于剪切到缓冲区

【x】:每按一次,删除光标所在位置的一个字符
【#x】:例如,【6x】表示从光标位置开始往后删除 6 个字符
【X】:每按一次,删除光标所在位置的前一个字符
【#X】:例如,【20X】表示删除光标所在位置的前 20 个字符
【dd】:删除光标所在行
【#dd】:从光标所在行开始删除 # 行

5.替换

【r】:替换光标所处的字符
【#r】:例如,【2r】表示从光标处开始往后 2 个字符全部替换成你输入的那个字符
【R】:替换光标所在之处的字符,直到按下【Esc】

6. 撤销

【u】:回到上一步操作,可以支持多次撤销
【ctrl + r】:撤销的回复

7.切换大小写

【shift + ~】:切换大小写


8. 更改(这里用替换即可)

【cw】:更改光标所在的字符到字尾处
【c#w】:例如,【c3w】表示更改 3 个字符

9. 跳转至指定行

【ctrl + g】:列出光标所在行的行号
【#G】:例如,【15G】表示移动光标至文章的第 15 行行首

5、vim末行模式命令集

1.批量化替换

【%s/printf/cout/g】:它会把文本里所有的 printf 替换成 cout

2.保存、退出vim

【w】:保存当前文本
【w!】:强制保存当前文本
【q】:退出 vim
【q!】:强制退出 vim
【wq】:保存退出
【wq!】:保存并强制退出

3.查找

【!man 3 函数名】:查看函数手册,按【q】回到命令模式
【/关键字】:查找字符或字符串,如果第一次找的关键字不是想要的,可以按 n 往后查找
【?关键字】:查找字符或字符串,如果第一次找的关键字不是想要的,可以按 n 往后查找
【#】:查找光标所在在的那个单词,如果不是想要的,按入 shift,然后一直 #

/ 和 ? 的查找有什么区别 ❓

/ 是从文本的开头开始往下查找,? 是从文本结尾开始往上查找。

4.编译执行

【!gcc 文件名】:在底行模式下可以直接进行编译
【!./a.out】:底行模式下执行程序
【!命令】:换言之在底行模式下可以在 ! 后跑任何命令 

5.列出行号

【set nu】:会在文本中的每一行列出行号,注意它只能在当前文件生效,且退出会失效,一劳永逸的方法在下面的 vim 配置就提到

6.分屏

【vs 文件名】:可以在当前窗口下新增一个窗口进行分屏,【ctrl + ww】可以将光标定位到另一个窗口,注意退出 vim 的窗口是光标所在的窗口

6、vim可视模式命令集

从命令模式下按 V 可进入到可视模式。

1. 批量化注释与取消注释

【ctrl+v】可以从可视模式下或正常模式下进入列模式,然后可以通过 h/j/k/l 来选中列,之后按大写 I 进入插入模式,输入注释符 // 后,按  Esc 键
【ctrl+v】进入列模式后选中所有的 //,然后按 d 即可删除


7、vim操作总结

  1. 三种模式

    命令模式
    插入模式
    底行模式
    
  2. vim 操作

    打开、关闭、查看、查询、插入、删除、替换、撤销、复制等 
    

实际我们通常在对文本进行操作时,不是死板的只能用命令模式,而是用命令模式 + 插入模式,怎么方便怎么来。

8、简单vim配置

对于 vim 配置其实是个不太好的主题。

💦 配置文件的位置
  1. 在目录 /etc/ 下,有个 .vimrc 的文件,这是系统中公共的 vim 配置文件,对所有用户都有效
  2. 而在每个用户的主目录下,都可以建立自己私有的配置文件,命名为 .vimrc。例如,/root 目录下,通常已经存在一个 .vimrc 文件,如果不存在,则自己创建
  3. 切换用户成为自己执行 su,进入自己的主工作目录执行 cd~
  4. 打开自己目录下的 .vimrc 文件,执行 vim .vimrc
💦 常用配置选项(用来测试)
  1. 设置语法高亮: syntax on
  2. 显示行号: set nu
  3. 设置缩进的空格数为 4: set shiftwidth = 4
  4. 更多可百度 vim 常用配置项



这里的配置是我们自己配的,比较简单,但实际上要配好 vim,是需要下各种各样的插件的,这其中的过程非常麻烦。

💦 使用插件(不推荐)

要配置好看的 vim,原生的配置可能功能不全,可以选择安装插件来完善配置,保证用户是你要配置的用户,接下来:

  1. 安装 TagList 插件,下载 taglist_xx.zip ,解压完成,将解压出来的 doc 的内容放到 ~/.vim/doc, 将解压出来的 plugin 下的内容拷贝到 ~/.vim/plugin
  2. 在 ~/.vimrc 中添加:Let Tlist_Show_One_File=1 let Tlist_Exit_OnlyWindow=1 let Tlist_Use_Right_Window=1
  3. 安装文件浏览器和窗口管理器插件:WinManager
  4. 下载 winmanager.zip,2.X 版本以上的
  5. 解压 winmanager.zip,将解压出来的 doc 的内容放到 ~/.vim/doc,将解压出来的 plugin 下的内容拷贝到 ~/.vim/plugin
  6. 在 ~/.vimrc 中添加 let g:winManagerWindowLayout='FileExplorer|TagList n map wm :WMToggle
  7. 然后重启 vim,打开 ~/XXX.c 或 ~XXX.cpp,在normal 状态下输入 “wm”。具体请稳步手把手教你把Vim改装成一个IDE编程环境(图文)
💦 gitee(推荐)

在 gitee 上有一键化安装配置 vim的方案(注意这里介绍的 vimforcpp 只支持 centos7):

  1. 在 gitee 上搜索关键字 vimforcpp
  2. 复制安装链接到我们的 xshell,按提示操作: 链接点击这里
  3. 安装成功,按提示使 vim 配置生效

  4. 这里配置完后,缩进用的是 2 个字符,所以我这里按照自己的习惯改成 4 个

9、vim配置参考资料(github)

Vim从入门到牛逼(vim from zero to hero)

10、sudo提升权限问题

这是在【Linux 权限】 中遗留的一个问题,曾经我们在普通用户的操作中,想使用 sudo 来短期提升权限,却并不能如愿,这是因为默认这个用户是不受信任的。解决方案:

  1. 先 su - 切换成 root,在 root 下操作
  2. vim /etc/sudoers 打开配置文件
    可以看到这里有条两条命令,
    其一是允许 root 用户在任何地方运行任何命令:

    其二是在这个组里的用户可以运行任何命令:
  3. 将普通用户添加到组里,保存并退出,注意这里需要 wq!,即使是 root 用户 wq 也不行,因为它是携保护的文件
  4. 完成

11、PacVim

PacVim 是用于学习 vim 指令的一款游戏:

  1. 安装 PacVim
    这款游戏源码托管在 github 上。

    $ git clone https://github.com/jmoon018/PacVim.git
    $ cd PacVim
    $ sudo make install
    
  2. 启动游戏

    $ pacvim
    $ pacvim [LEVEL_NUMER] [MODE]
    

    默认从头开始玩游戏。如果不想,其中 LEVEL_NUMER 表示关卡号,MODE 表示难度,n 为正常模式、h 为困难模式,例如 pacvim 3 h 表示第 3 关困难模式。

  3. 退出游戏

    【Esc/q】
    

四、Linux编译器 —— gcc/g++的使用

在此之前,我们可以使用命令 gcc -v 、g++ -v 查看 gcc、g++ 有没有安装:

1、背景知识

我们的 C 代码写完,要变成可执行程序需要四个阶段:

  1. 预处理
  2. 编译
  3. 汇编
  4. 链接

为啥不能直接将 C语言转成二进制 ❓

它跟历史有关,早期编程可以认为是电路开关,往后是 0 1 指代,再往后有了汇编语言,在这时计算机就出现了编译器的概念了。比如时间回到 C语言诞生之时,现在有两种方案:要么把 C语言转成汇编,再转二进制;要么把 C语言直接转二进制。在计算机这门学科中永远是站在巨人的肩膀上学习的,把 C语言直接转二进制的成本一定会比把 C语言转成汇编,再转二进制的成本要高的。

注意 gcc 可以编译 C,但不能编译 C++;g++ 可以编译 C、C++。除了 C/C++,Linux 下几乎可以直接在命令行中执行大部分后端语言,比如 python、java 等。

当学完了 vim,那么以后的 C++ 代码、刷题都可以在 Linux 下进行操作,在刷题时,大部分的后端判题的系统都是 Linux,所以有时你会发现在做题时,在 VS 下是对的,提交却是错的,除了测试用例不全面,也有可以代码中包含了 windows 相关内容,如 windows.h 的头文件。

2、gcc如何完成

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

💦 预处理(进行宏替换等)
  1. 预处理功能主要包括头文件展开、条件编译、去掉注释、宏替换等
  2. 预处理指令是以 # 号开头的代码行
  3. 实例:gcc –E test.c –o test.i
    选项 “-E” 该选项的作用是让 gcc 在预处理结束后停止编译过程,选项 “-o” 是指目标文件,“.i” 文件为已经经过预处理的干净的 C 原始程序

💨test.c

💨test.i

💦 编译(生成汇编)
  1. 在这个阶段中 gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言

  2. 用户可以使用 “-S” 选项来进行查看,该选项只进行编译而不进行汇编,其中生成的 “.s” 文件就是汇编语言

  3. 实例: gcc –S test.i -o test.s

💨test.s

虽然我们不学汇编,但至少得大概认识

💦 汇编(生成机器可识别代码)
  1. 汇编阶段是把编译阶段生成的 “.s” 文件转成目标文件
  2. 读者在此可使用选项 “-c” 就可以看到汇编代码已经转换为 “.o” 的二进制目标文件了
  3. 实例: gcc –c test.s -o test.o

💨test.o

💦 链接(生成可执行文件或库文件)
  1. 在成功编译之后就进入了链接阶段
  2. 实例:gcc test.o -o mytest

💨执行 mytest

在本文中重点还要学习链接的过程,也就是下面动态库和静态库的概念。

💦 gcc选项
-E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面 
-S 编译到汇编语言,不进行汇编和链接 
-c 编译到目标代码
-o 文件输出到文件
-static 此选项对生成的文件采用静态链接
-g 生成调试信息,GNU 调试器可利用该信息
-shared 此选项将尽量使用动态库,所以生成的文件比较小,但是需要系统调动态库
-O0
-O1
-O2
-O3 编译器优化选项的 4 个级别,-O0 表示没有优化,-O1 为缺省值,-O3 优化级别最高
-w  不生成任何警告信息
-Wall 生成所有警告信息

💦 gcc选项记忆

为了方便记忆,我们可以看看键盘的左上角的 Esc 键,它刚好对应我们的 -E、-S、-c 选项;而生成的文件的后缀刚好对应镜象文件的后缀 .iso。

💦 函数库

我们的 C 程序中,并没有定义 “printf” 的函数实现,并且我们发现在预处理中包含的 “stdio.h” 中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实 “printf” 函数的呢 ❓

原因是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径 “/usr/lib” 下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数 “printf” 了,而这也就是链接的作用。

💦 静态库和动态库
  1. 静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了,其后缀名一般为 “.a”。
  2. 动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为 “.so”,如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件,如后所示。 gcc hello.o –o hello。Linux 下编译好一个程序,默认情况下是属于动态链接形成的可执行程序

    ldd 命令查看 mytest 所依赖的库;file 辨别 mytest 的类型。

📝小故事助理解

一般我们写的程序中,大部分都是动态链接,因为动态链接中不需要把库中的内容过多的拷贝,所以相对而言,它的编译效率较高,这是其一;其二,有时候我们下一些软件,比如 VS2017,它上面会有一些组件 C++、C# 等,这些组件并没有在你的硬盘中,而当你要安装时,它会帮你找到这些组件下载,这样有个好处就是咱需要啥就下啥,而不是直接一堆东西装在机器上,而自己需要使用的组件寥寥无几,所以这里就使用动态库的方式实现。一般在服务器上大部分也都是动态链接,不过有时需要将服务在很多机器上部署,那么单纯的动态链接有可能会出问题,因为动态链接是在程序运行之后才去对应加载到内存中,万一有一个库丢失了,那么程序就挂了。所以有时候一些程序它也会采用静态链接,它的好处就是它不依赖任何的动态库,坏处也很明显,效率低。比如静态链接的大小是动态链接的一百倍,要把静态链接这个程序下下来,只能全部下下来,而动态链接是边下边用。总的来说,它俩各有利弊。

比如你是一个新入学的大一新生,你在写作业,突然有了一个上网的需求,因为环境不熟悉,所以问了学长附近的网吧,随后就去玩了一个钟,接着回来继续写作业,这叫动态链接,它生成的可执行程序只包含你的代码及你要使用外部函数的链接。

后来大三了,要准备找工作了,家里给买了台电脑,当你正在学习时,你想上网,就不用去网吧了,只需要打开自己的电 脑玩个一个钟后又继续学习,也就是说静态链接,并没有和外界产生关联。所以静态链接本质就是将库里的代码拷贝到自己的可执行程序里。

📝小结

动态链接的生成的可执行程序的体积往往比较小,但是它依赖第三方库,有一定的风险,万一网吧被查封了。

静态链接虽然生成的可执行程序的体积较大,但是它不依赖第三方库,你有自己的电脑,网吧被查封了,照样可以玩,就是开学、放寒暑假不方便。

动态链接改静态链接 ❓

注意在新版本的 Linux 系统下一般都不会安装 libc.a,只会安装 libc.so,所以就使用不了 -static,解决方法就是安装 glibc-static

sudo yum install glibc-static


可以看到光是一个简单的程序,静态链接的大小就比动态链接高出 100 倍以上。最后关于动静态库的更多细节在后面的学习中会慢慢摸索。

五、Linux调试器 —— gdb使用

1、背景

这里我们对以下代码不理解,需要调试:

对我们编译好的可执行程序 mytest 进行 gdb:

这是因为 Linux 中默认生成的可执行程序是 release 版本的, 如果需要 debug 版本,就得加上 -g 选项:

Linux 中生成的可执行程序,它的二进制的格式是 elf 的,readelf 可以读取内部的格式:

我们可以使用选项 -S 查看可执行程序的分段情况:

gdb 调试 debug 版本:

  1. 在 C语言阶段我们就了解过了程序的发布方式有两种,debug 模式和 release 模式
  2. Linux gcc/g++ 出来的二进制程序,默认是 release 模式
  3. 要使用 gdb 调试,必须在源代码生成二进制程序的时候,加上 -g 选项

一个项目的开发流程 ❓

注意对于上图中的测试来说严格来说并不是测开,如果产品迭代更新,bug 修复等,严格来说就得重新测试,包括上代产品测试过的,这样成本较高,所以就诞生了很多自动化测试的开发需求,这就是测开,所以一般这里成本较低的一些脚本语言做的,如 python。

2、开始使用

ctrl + d/D 或 quit/q:退出调试
list/l 行号(, 行号):显示 binFile 源代码,显示的是当前行号周围的代码,可以利用另一个行号来指定一段区间
list/l 函数名:列出某个函数的源代码
r 或 run:运行程序
n 或 next:单条执行
s 或 step:进入函数调用
break(b) 行号:在某一行设置断点
break 函数名:在某个函数开头设置断点
info break/i b:查看断点信息
finish:执行到当前函数返回,然后停下等待命令
print(p):打印表达式的值,通过表达式可以修改变量的值或调用函数,类似于 p
p/P 变量:打印变量值
set var:修改变量的值
continue 或 c:从当前位置开始连续而非单步执行程序
delete breakpoints/d 或 d:删除所有断点
delete breakpoints n 或 d n:删除序号为 n 的断点
enable (breakpoints) 序号:启用断点,默认全启
disable 序号:禁用断点,默认全禁
display 变量名:跟踪查看一个变量,每次停下来都显示它的值
undisplay:取消对先前设置的那些变量的跟踪
until X 行号:跳至 X 行
breaktrace 或 bt:查看各级函数调用及参数
info (i) locals:查看当前栈帧局部变量的值
quit:退出 gdb

调试代码(入门) ❗

  1. l + 行号(, 行号),显示的是当前行号周围的代码,按回车继续往下显示,直到全部显示完

  2. b + 行号,打断点

  3. i + b,查看断点

  4. r,运行程序(调试)

  5. n,单步执行,继续执行可按 n/Enter(gdb 可以记录历史执行的命令)

  6. p + 变量,查看变量(监视),当循环往下走时,它不会变化,所以它用于查看一次

  7. display + 变量,跟踪查看一个变量,每次停下来都显示它的值

  8. undisplay + 变量序号,取消对先前设置的那些变量的跟踪

  9. c,循环还没走完,想直接跳出循环到下一个断点处(因为我已经确定这个循环是对的)

  10. 结束调试,使用 ctrl + d 或 quit,退出调试

调试代码(进阶),主要演示剩余的指令 ❗

  1. 设置断点

  2. d n,删除序号为 n 的断点;d,删除所有断点
    注意如果删除断点,下一次再加断点,它的 Num 是递增的,除非把 gdb 退出

  3. 设置了 17 行和 24 行的断点,并 r,接着 n 往下走执行 scanf
    注意空行会直接跳过

  4. 这里我们想进入函数内部,先试用 n
    发现它并没有进入,说明 n 是逐过程执行

  5. 重新调试可以再 r

  6. 这里想进入函数内部可以使用逐语句命令 s

  7. bt,查看调用堆栈

  8. a)现在在 Sum 内的循环里,想跳出循环到 return,Sum 里没断点,不能用 c
    until 行号,跳转到指定行号

    b)现在在 Sum 内的循环里,想跳出到 20 行等待,除了使用 until 外,更规范的的还可以使用 finish,执行到当前函数返回,然后停下等待命令,注意不能 finish main 函数


    c)现在在 Sum 内的循环里,想跳到下一个断点处可以直接 c

  9. disable (序号),断点禁用,默认是全禁;
    enable breakpoints (序号),断点启用,默认是全启

  10. 如果在循环里有 100 次循环,想将循环跑到第 80 次可以 set var

📝 小结

最后想必很多同学会觉得 gdb 相比 VS 的调试成本就高的多,其实那是 gdb 用的不熟练导致的,如果熟练了其实可以说它俩的效率是等价的
实际对于 gdb,在往后的编程中用的不多,不用则已,一用惊人,所以还是得了解的。

3、理解

相信大家对 Visual Studio 2017 已经不陌生了,这里为了方便记忆,可以对应 VS 的操作来进行理解记忆

b 行号 ↔ F9 
r ↔ F5
c ↔ F5
n ↔ F10
s ↔ F11
q ↔ shift + F5

六、Linux项目自动化构建工具 —— make/makefile

在此之前对于一个多文件的项目,它们之间的关系是 VS 帮我们维护处理的,而在 Linux 中需要我们自己来维护处理。

1、背景

  1. 会不会写 makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
  2. 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile 定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至进行更复杂的功能操作
  3. makefile 带来的好处就是 “自动化编译”,一旦写好,只需要一个 make 命令,整个工程完全自动编译,极大的提高了软件开发的效率
  4. make 是一个命令工具,是一个解释 makefile 中指令的命令工具,一般来说,大多数的 IDE 都有这个命令,如:Delphi 的 make,Visual C++ 的 nmake,Linux 下 GNU 的 make。可见,makefile 都成为了一种在工程方面的编译方法
  5. make 是一条命令,makefile 是一个文件,两个搭配使用,完成项目自动化构建

2、依赖关系

其次我们再了解一下什么是 make,什么是 makefile:

  1. make 是一条命令,它可以帮我们自动化构建项目

  2. makefile 是一个文件,自动化构建项目的过程是它完成的

    这个文件里包含目标文件和原始文件的依赖关系和依赖方法。

3、依赖方法

如上

4、文件清理

  1. 文件除了被创建,也是需要被清理的
  2. 像 clean 这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要 make 执行。即命令 —— “make clean”,以此来清除所有的目标文件,以便重编译
  3. 但是一般我们这种 clean 的目标文件,我们将它设置为伪目标,用 .PHONY 修饰,伪目标的特性是,总是被执行的

5、理解

如下实例

6、实例代码

  1. touch makefile/Makefile
    注意 m 可以大写,但不能写错

  2. vim Makefile 表明依赖关系和依赖方法后 wq
    注意依赖方法也就是第二行是以 Tab 开头,并不能以 4 个空格

  3. make 直接编译代码

  4. vim Makefile 清理文件
    一个项目不仅需要能生成文件,还要能清理文件

  5. make clean 清理文件

  6. vim Makefile 用符号简化
    $^ 表示所有依赖的文件
    $@ 表示目标文件

  7. 多文件项目的构建

    注意生成的 mytest 需要依赖 mytest.c、main.c,而 mytest.h 则已经被它们包含了

📝说明

4 ❓

.PHONY 表示定义伪目标,它的意义是 make clean 时 clean 总是可执行的
这个 clean 没有依赖关系,但有依赖方法

什么叫总是可执行的 ?

其中 mytest 和 clean 都是目标文件,只不过 mytest 没有用 .PHONY 修饰,所以 clean 使用 .PHONY 修饰后就由总是不被执行的转换成总是可执行的。

验证 !

但是我们通常不会把目标可执行程序设置成总是可执行的,因为每次编译它都是有成本的,你只要保证程序是最新的,也就是说当你去 vim 原始文件后,它就可以再 make。

Makefile 里有两个目标文件,make mytest 执行 gcc,make clean 执行 rm,为什么 make 可以默认执行 gcc ?

因为 Makefile 在进行自上向下搜索目标文件时,默认生成第一个可执行程序后就不会往下搜索生成了,也就是说 Makefile 默认只生成一个目标文件。

验证 !


注意一般为了符合习惯,不那么写。

make/makefile 实现 一个 C 文件到可执行程序 ❓

验证 !

7、原理

make 是如何工作的,在默认方式下,也就是我们只输入 make 命令:

  • make 会在当前目录下找名字叫 “Makefile” 或 “makefile” 的文件
  • 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,它会找 “mytest” 文件,并把这个文件作为最终的目标文件
  • 如果 “mytest” 文件不存在,或是它所依赖的的后面的 “mytest.o” 文件的修改时间要比 “mytest” 这个文件新(可以用 touch 测试),那么,它就会执行后面所定义的命令来生成 “mytest” 这个文件
  • 如果 “mytest” 所依赖的 “mytest.o” 文件不存在,那么 make 会在当前文件中找目标为 “mytest.o” 文件的依赖性,如果找到则再根据那一个规则生成 “mytest.0” 文件(类

    linux工具:软件包管理器yum|编辑器vim|编译器gcc/g++|调试器gdb|自动化构建工具make/makefile|linux小程序:进度条|git命令行(代码片段)

    文章目录【写在前面】一、Linux软件包管理器yum💦什么是软件包💦如何安装软件💦如何卸载软件💦关于rzsz💦注意事项💦查看软件包二、Linux开发工具三、Linux编辑器——vim的使用1、vim的基本概念2、vim的... 查看详情

    linux环境基础开发工具的使用(代码片段)

    文章目录Linux软件包管理器yum软件包查看软件包安装软件卸载软件Linux编辑器-vim使用vim的基本概念vim的基本操作vim正常模式命令集vim末行模式命令集简单vim配置Linux编译器-gcc/g++使用Linux调试器-gdb使用Linux项目自动化构建工... 查看详情

    《linux从0到99》三yum与vim编辑器(代码片段)

    yum软件包管理器和vim编译器1.yum软件包管理器01什么是软件包02查看软件包03如何安装软件04如何卸载软件2.vim编辑器01vim的优点a)高效率移动b)高效的输入02vim的基本概念03vim的基本操作04vim正常模式命令05vim末行模式命令06修改v... 查看详情

    linux环境及工具(yum/vim/gcc/g++/gdb/make/makefile)(代码片段)

    【Linux学习】Linux环境及工具零、前言一、Linux软件包管理器yum1、yum介绍2、rzsz2、yum工具的基本操作1)查看软件包2)安装软件3)卸载软件二、Linux开发工具vim1、vim的介绍2、vim基本操作3、vim正常模式命令集4、vim底行模式命令集5、vim... 查看详情

    linux基础开发工具使用(yum,vim,gcc/g++,gdb,make,git)(代码片段)

    文章目录一.Linux软件包管理器yum(1).软件包和软件包管理器(2).ping指令(3).查看软件包(4).安装软件(5).卸载软件二.Linux编辑器-vim使用(1).vim基本概念(2).vim模式切换(3).vim命令模式命令集(1).移动光标(2).复制(3).撤销上一次操作(4).删除文... 查看详情

    linux环境基础开发工具使用(代码片段)

    目录:Linux软件包管理器yum什么是软件包关于rz、sz查看软件包如何安装软件如何卸载软件总结:Linux开发工具---编辑器vim使用1.vim的基本概念2.vim的基本操作3.vim正常模式命令集4.vim末行模式命令集5.vim操作总结6.简单vim配置... 查看详情

    linux环境基础开发工具使用(代码片段)

    目录:Linux软件包管理器yum什么是软件包关于rz、sz查看软件包如何安装软件如何卸载软件总结:Linux开发工具---编辑器vim使用1.vim的基本概念2.vim的基本操作3.vim正常模式命令集4.vim末行模式命令集5.vim操作总结6.简单vim配置... 查看详情

    linux开发工具的使用(代码片段)

    Linux开发工具一、Linux软件包管理器yum?什么是软件包关于rzsz查看软件包如何安装软件如何卸载软件二、Linux编辑器-vim使用vim基本概念vim的基本操作vim正常模式命令集vim末行模式命令集三、Linux编译器-gcc/g++使用背景知... 查看详情

    linux之基础开发工具的应用(代码片段)

    Linux之基础开发工具的应用一、Linux软件包管理器yum什么是软件包注意事项查看软件包如何安装软件如何卸载软件二、Linux编辑器-vim使用1.vim的基本概念三、Linux编译器-gcc/g++的使用1.背景知识2.函数库3.gcc选项一、Linux软件包... 查看详情

    linux——环境基础开发工具的使用(代码片段)

    目录一、Linux软件包管理器—yum1.Linux下软件安装的方式2.如何查看Linux下的软件包 3.利用yum来安装相应的软件4.利用yum来进行软件的卸载5.如何实现云服务器与本地机器间的文件互传 6.注意事项 二、Linux编辑器—vim的使用1.vim常... 查看详情

    linux万字详解linux开发工具(yum,vim,gcc/g++,gdb,make/makefile)(代码片段)

    文章目录一、软件包管理器yum1.什么是软件包2.ping3.查看所有软件包4.安装软件包5.卸载软件包二、编辑器vim0.vim的配置(1)配置文件(2)配置vim1.vim的模式2.模式间的转变3.命令模式(Normalmode)(1)命令模式... 查看详情

    linux篇第三篇——linux环境下的工具(yum+vim+gcc/g+++gdb)(代码片段)

    ...器gcc和g++,还有代码调试器gdb等。目录🌏软件包管理器yum🌲介绍🌲使用方法🌲rzsz工具🌏vim编辑器🍯概念🍯vim正常模式下的命令🍯vim底行模式的命令🍯简单的vim配置🌏编译器g... 查看详情

    linux——基础开发工具和vim编辑器的基本使用方法

    目录Linux软件包管理器yumLinux编辑器-vim使用1.vim的基本概念      2.vim的基本操作3.vim正常模式命令集4.vim末行模式命令集如何配置vimLinux软件包管理器yumyum是Linux下的一个下载软件的软件对于yum,现阶段只需要会使用yum的三... 查看详情

    linux下的软件包管理器(yum),编译器(vim),编译器(gcc/g++),调试器(gdb)使用大汇总(代码片段)

    目录一.软件管理器yum    1.1概念     1.2查看软件包    1.3安装软件包    1.4卸载软件包 二.编辑器vim    2.1概念    2.2vim的基本操作    2.3vim命令模式下的命令集    2.4末行模式命令集三.编译器gcc/g++    3.... 查看详情

    linuxlinux环境基础开发工具使用介绍(代码片段)

    Linux环境基础开发工具使用介绍(一)一.Linux软件包管理器yum的使用1.什么是软件包2.查看软件包3.如何安装软件4.如何卸载软件5.lrzsz的安装和使用6.yum安装有意思的小程序二.Linux编辑器-vim使用1.vim的基本概念2.vim的基本操... 查看详情

    linux环境基础开发工具的使用

    文章目录Linux软件包管理器yum什么是软件包查看软件包安装软件卸载软件Linux编辑器-vimvim的基本概念vim的基本操作vim正常模式命令集vim末行模式命令集Linux编译器-gcc/g++背景知识gcc/g++的编译预处理编译汇编链接静态库... 查看详情

    linux学习笔记

    Linux开发工具🍬目录Linux开发工具🍬💻Linux安装软件💻💻Linux软件包管理器yum💻💻Linux编辑器-vim的使用💻普通模式📖末行模式📖vim配置📖末尾📖💻Linux安装软件& 查看详情

    linux环境基础开发工具的使用(yumvimgccg++gdbmake/makefile)(代码片段)

    文章目录Linux软件包管理器-yumLinux下安装软件的方式认识yum查找软件包安装软件如何实现本地机器和云服务器之间的文件互传卸载软件Linux编辑器-vimvim的基本概念vim下各模式的切换vim命令模式各命令汇总vim底行模式各命令汇总vim... 查看详情