【Linux】Linux基础开发工具从入门到实践
前言:学了Linux的指令,再就是Linux基础开发工具,熟练掌握基础开发工具是提升效率的关键。本文学习Linux的基础开发工具,无论是软件安装、代码编辑,还是编译调试、版本控制,一套顺手的工具链能让你在开发路上少走很多弯路。本文将结合实战,详细讲解 Linux 下核心开发工具的使用方法。
一、软件包管理器
1.1 什么是软件包/软件管理器?
软件包
:简单来说就是,开发人员把软件提前编译好,并且做成软件包(即安装程序)放在服务器上(APP)
软件管理器
:通俗来说就是管理软件包的(应用商店),能自行解决依赖关系、下载和安装软件包。
yum
(yellow dog updater modified):Linux下非常常用的一种包管理器,主要用于Centos,RedHat等apt
:也是一种包管理器,多用于Ubuntu 。
1.2 Linux软件生态
操作系统的好坏评估,就是看其生态问题,首先有一个问题:为什么会有人免费给特定社区提供软件,还发布?还提供云服务器让你下载?
是因为要提供相关软件与云服务,构建专属生态,增强社区粘性与影响力。一个软件有一个好的生态环境,就会有更多人去使用,讨论问题,分享经验,解决问题,如Linux的生态环境。
- 下载软件的图示过程:
还有一个问题,国外发行的软件版本,国内是怎么用上的呢?
国内的一些社会性公司会购买国外的软件包服务器,将该服务器内的软件等拷贝到国内的软件包服务器上,然后上线到国内的一些网站上,即镜像网站。
一些镜像网站:
- 阿里云:https://developer.aliyun.com/mirror/
- 清华大学:https://mirrors.tuna.tsinghua.edu.cn/
- 中科大:http://mirrors.ustc.edu.cn/
- 北交大:https://mirror.bjtu.edu.cn/
- 中科院软件研究所:http://mirror.iscas.ac.cn/
- 上交大:https://ftp.sjtu.edu.cn/
1.3 具体操作:查装卸
(1)基础操作对比(centos vs ubuntu)
- 安装/卸载需
sudo
权限(修改系统目录) - 同一时间只能执行一个
yum/apt
操作(防冲突)
二、编辑器vim:Linux下的“代码神器”
Vim 是 Linux 下功能最强大的文本编辑器之一,兼容 Vi 且支持语法高亮、多模式编辑,掌握它能极大提升代码编写效率。本节聚焦 Vim 核心模式与实用操作,帮你快速上手。
IDE例子:
2.1 核心认知:Vim和Vi的区别
vi
:Linux的原生编辑器,功能基础vim
:vi的升级版,支持语法高亮、可视化操作,兼容所有vi命令,可视化操作不仅可以在终端运行,也可以运行于 x window、mac os 、windows等
2.2 vim的三大核心模式:切换是关键
三大核心模式:命令模式(command mode)、插入模式(insert mode)和底行模式(last line mode)
Esc
i
(光标前)/a
(光标后)/o
(新行)Esc
shift+;
(即:
)Esc
或执行命令后自动返回2.3 vim的实用操作:从入门到高效
(1)vim基础操作:
- 进入vim,在系统提示符输入
vim 文件名称
,即可进入vim全屏幕编辑画面,但是刚进入时是处于正常模式
,要切换到插入模式
才可以输入文字 正常模式
切换至插入模式
:直接输入==a/i/o==插入模式
切换至正常模式
:Esc正常模式
切换至底行模式
:shift+;- 退出vim模式并且保存文件:在正常模式下,按shift+; (即 : )进入底行模式后,输入下面的命令:
(2)vim正常模式命令集:
1.插入模式:
- 正常模式下按i进入插入模式后是从光标当前位置开始输入文件
- 按 a 进入插入模式是从当前光标所在位置的下一个位置开始输入文字
- 按 o 进入插入模式是插入新的一行,从行首开始输入文字
2.移动光标:
- vim可以直接用键盘上的光标来上下左右移动,即小写英文字母的h、j、k、l,分别控制光标左、下、上、右
G:
移动到文章的最后$/^:
移动到光标所在行的行尾/行首w/e:
光标跳到下个字的开头/字尾b:
光标回到上个字的开头nl:
光标回到该行的第n个位置,如:5l,6lgg
:进入到文本开始shift+g
:进入到文本末端Ctrl+b/f
:屏幕往后/前移动一页ctrl+u/d
:屏幕往后/前移动半页
3.删除文字:
x
:每按一次,删除光标所在位置的一个字符nx
:即删除光标所在位置的“后面(包括自己在内)”n个字符(n代表数字)X
:大写的X,每按一次,删除光标所在位置的“前面”一个字符nX
:即删除光标所在位置的“前面”n个字符(n代表数字)dd
:删除光标所在行ndd
:从光标开始删除n(n代表数字)行
4.复制
yw
:将光标所在之处到字尾的字符复制到缓冲区nyw
:复制n个字到缓冲区yy
:复制光标所在行到缓冲区nyy
:拷贝n行到缓冲区p
:将缓冲区的字符贴到光标所在位置
5.替换:
r
:替换光标所在处的字符R
:替换光标所到之处的字符,直到按下ESC键为止
6.撤销上一次的操作:
u
:撤销(相当于Windows的CTRL+z)ctrl+r
:对 u的恢复,即撤销u
7.更改:
cw
:更改光标所在处的字到字尾处cnw
:更改n个字
8.跳至指定的行:
ctrl+g
:列出光标所在行的行号nG
:移动到光标至文章的第n行行首
(3)vim底行模式命令集:
在使用底行模式之前,先按ESC键确认已处于正常模式,再按shift+;
进入底行模式
2.4简单配置:更好用
vim配置分为两类,推荐自定义,用起来更顺手(不影响系统全局)
- 进入用户主目录:
cd ~
- 编辑配置文件:
vim .vimrc
- 常用配置项如下(举例):
syntax on \" 开启语法高亮 set nu \" 显示行号 set shiftwidth=4 \" 缩进4个空格 set tabstop=4 \" Tab键对应4个空格
【注】还有很多配置,可以按照喜好配置
三、GCC/G++编辑器:从源代码到可执行文件
GCC(C编辑器)与G++(C++编辑器)是Linux下编译C/C++代码的核心工具,掌握其编译流程与参数,能更好的理解代码“如何变程序”
3.1编译四步曲:层层递进的过程
以C语言代码为例,GCC编译选项:gcc 选项 要编译的文件 选项 目标文件
从.c
源代码到可执行文件,需经历:预处理->编译->汇编->链接
四步,每一步都可通过GCC选项独立控制:
-E
:让gcc在预处理结束后停止编译过程-o
:是指目标文件.i
:文件为已经过预处理的C原始程序-S
:进行查看,该选项只进行编译而不进行汇编,生成汇编代码-c
:查看汇编代码是否已转化为二进制代码了
3.2 核心概念:静态链接VS动态链接
链接本质:关联代码与依赖库(如printf依赖于libc.so)
(1)静态链接:编译时将库代码全部嵌入可执行文件,生成文件大,所以运行时无需再依赖库(.a
), 在执行的时候运行速度快,编译命令:gcc hello.c -o hello -static(需提前安装静态库)
静态链接的缺点很明显:
- 浪费空间:每个可执行程序中对所有需要的目标文件都要有一份副本,若是多个程序对同一个目标文件都有依赖,导致同一个目标文件都在内存存在多个副本
- 更新比较困难:每当库函数的代码修改了,这个时候就需要重新进行编译链接形成可执行程序。
(2)动态链接:编译时仅记录库依赖,运行时家住在系统中的动态库(后缀.so
),生成文件小,节省内存,编译命令:gcc hello.o -o hello
(在执行中更常用动态链接,所以默认是动态连接的)
- 可通过
ldd 可执行文件名
查看依赖的动态库
【注 】:
- Linux下,动态库是XXX.so,静态库是XXX.a
- Windows下,动态库是XXX.dll,静态库是XXX.lib
3.3 常用GCC选项:调试与优化
四、Makefile:自动化构建的“工程管家”
当项目有多个源文件时,手动执行gcc命令效率极低。Makefile定义了编译规则,只需一个make
命令即可完成自动化构建,是大型项目的必备工具。
make
是一条命令,Makefile
是一个文件,两个搭配使用,完成项目的自动化构建
4.1 核心逻辑:依赖关系与依赖方法
Makefile的核心是:目标文件->依赖文件->编译命令,即:
目标文件:依赖文件1 依赖文件2 ...编译命令 (必须以Tab开头)
基本使用操作:
示例代码:myfile.c
#includeint main(){printf(\"hello world\\n\");return 0;}
Makefile文件:
//目标:myfile,依赖:myfile.cmyfile:myfile.cgcc -o myfile myfile.c //编译命令//伪目标:clean(清理生成文件,总是被执行,即每make一次,文件的属性时间就更新一次).PHONY:cleanclean:rm -f myfile //清理命令:删除可执行文件
推导过程:
myfile:myfile.ogcc myfile.o -o myfilemyfile.o:myfile.sgcc -c myfile.s -o myfile.omyfile.s:myfile.igcc -S myfile.i -o myfile.smyfile.i:myfile.cgcc -E myfile.c -o myfile.i.PHONY:cleanclean:rm -f *.i *.s *.o myfile
4.2 进阶用法:变量与函数
通过变量和函数简化Makefile(适配多文件项目),示例如下:
BIN=myfileCC=gccSRC=$(wildcard *.c) //使用wildcard函数,获取当前所有的.c文件OBJ=$(SRC:.c=.o) //将SRC的所有同名.c替换成为.o形成目标文件列表LFLAGS=-oFLAGS=-cRM=rm -f$(BIN):$(OBJ)@$(CC) $(LFLAGS) $@ $^ //$@代表文件名;$^代表依赖文件列表@echo \"linking... $^ to $@\" %.o:%.c //%.c展开当前目录的所有.c;%.o同时展开所有同名的.o@$(CC) $(FLAGS) $< //%<:对展开的依赖.c文件,一个一个交给gcc@echo \"compling ... $< to $@\" //@:不回显命令.PHNOY:cleanclean:$(RM) $(OBJ) $(BIN)
五、实践:编写第一个Linux程序–进度条
掌握了前面的工具,那么来实战编写一个动态进度条,理解“行缓冲区”“回车换行”等Linux终端特性
5.1 补充知识:回车(\\r)与换行(\\n)
换行
:光标移动到下一行开头回车
:光标移动到当前行开头(不换行)动态进度条的核心
:用\\r覆盖当前行内容,实现“实时更新”效果
5.2 核心原理:行缓冲区刷新
printf输出默认会缓存,需手动刷新缓冲区(fflush(stdout))才能实时显示,对比示例:
#includeint main(){// 示例1:无 \\n 且不刷新,3秒后才显示 printf(\"hello\"); sleep(3); // 示例2:加 fflush 实时显示 printf(\"hello\");fflush(stdout); sleep(3);return 0;}
5.3进度条代码实现(含Makefile)
(1)文件结构
progress/ ├── process.c # 进度条逻辑 ├── process.h # 函数声明 ├── main.c # 主函数(模拟下载) └── Makefile # 自动化构建
(2)核心代码(process.c)
#include \"progress.h\"#include #include #include // 进度条长度(100个字符对应100%)#define BAR_LENGTH 100// 基础版进度条:模拟从0%到100%的过程void progress_basic() { // 存储进度条字符 char bar[BAR_LENGTH + 1] = {0}; // 旋转光标字符集(实现动画效果) const char *spin = \"|/-\\\\\"; int spin_index = 0; // 从0%循环到100% for (int i = 0; i <= 100; i++) { // 填充进度条 memset(bar, \'=\', i); // 计算旋转光标位置 spin_index = i % 4; // 输出进度条: // [%-100s] 左对齐,占100个字符宽度 // %d%% 显示百分比 // %c 显示旋转光标 // \\r 回到行首 printf(\"[%-100s][%3d%%][%c]\\r\", bar, i, spin[spin_index]); // 手动刷新缓冲区 fflush(stdout); // 延迟50ms,控制进度条速度 usleep(50000); } // 进度完成后换行 printf(\"\\n\");}// 进阶版进度条:支持自定义任务量和样式void progress_advanced(int total, int current, char style) { // 边界检查 if (current < 0) current = 0; if (current > total) current = total; // 计算进度百分比 int percent = (int)((float)current / total * 100); // 构建进度条 char bar[BAR_LENGTH + 1] = {0}; int filled = (int)((float)current / total * BAR_LENGTH); memset(bar, style, filled); // 输出进度信息 printf(\"Progress: [%-100s][%3d%%] %d/%d\\r\", bar, percent, current, total); fflush(stdout); // 完成时换行 if (current == total) { printf(\"\\n\"); }}
(3)头文件(process.h)
#ifndef PROGRESS_H#define PROGRESS_H// 基础版:固定样式进度条void progress_basic();// 进阶版:可自定义参数的进度条// 参数:// total: 总任务量// current: 当前完成量// style: 进度条填充字符void progress_advanced(int total, int current, char style);#endif
(4)测试主程序(main.c)
#include \"progress.h\"#include int main() { // 测试基础版进度条 printf(\"基础版进度条演示:\\n\"); progress_basic(); printf(\"\\n\"); // 测试进阶版进度条(模拟文件下载) printf(\"进阶版进度条演示(模拟文件下载):\\n\"); int file_size = 1024; // 模拟文件大小1024KB for (int downloaded = 0; downloaded <= file_size; downloaded += 32) { progress_advanced(file_size, downloaded, \'#\'); usleep(100000); // 延迟100ms } return 0;}
(5)Makefile
# 编译器CC = gcc# 编译选项:显示警告,生成调试信息CFLAGS = -std=c99 -Wall -g# 目标可执行文件TARGET = progress_bar# 源文件SRCS = progress.c main.c# 目标文件OBJS = $(SRCS:.c=.o)# 默认目标:编译程序all: $(TARGET)# 链接目标文件生成可执行文件$(TARGET): $(OBJS) $(CC) $(CFLAGS) -o $@ $^# 编译源文件生成目标文件%.o: %.c $(CC) $(CFLAGS) -c $< -o $@# 清理编译生成的文件clean: rm -f $(OBJS) $(TARGET)# 伪目标:避免与同名文件冲突.PHONY: all clean
效果展示: