Linux 开发环境与工具链

从Linux基础工具到编译调试、版本控制,一套完整的开发环境与工具链,是入门系统编程的必备基石。


1. 软件包管理器

1.1 核心概念

软件包:提前编译好的程序,类似 Windows 的 .exe 安装包。

包管理器:用于查找、下载、安装、卸载软件包的工具,类似手机应用商店。

CentOS/RHEL:yum (Yellowdog Updater, Modified)

Ubuntu/Debian:apt (Advanced Package Tool)

操作系统生态:决定系统易用性,包含社区论坛、官网文档、软件体系、维护更新速度、系统本身、用户群体。

1.2 软件包依赖

软件之间存在依赖关系(如你的软件依赖 libc.solibc.so 又依赖 ssl.so),包管理器会自动解决依赖。

1.3 yum/apt 常用操作

查看软件包

bash 复制代码
# CentOS
yum list | grep lrzsz
# Ubuntu
apt search lrzsz
apt show lrzsz

安装软件

bash 复制代码
# CentOS
sudo yum install -y lrzsz
# Ubuntu
sudo apt install -y lrzsz

卸载软件

bash 复制代码
# CentOS
sudo yum remove [-y] lrzsz
# Ubuntu
sudo apt remove [-y] lrzsz

注意事项:安装需要 sudo 或 root 权限,同一时间只能运行一个 yum/apt 进程。必须保证网络畅通(可 ping www.baidu.com 验证)。

1.4 安装源配置

CentOS:源文件路径 /etc/yum.repos.d/

Ubuntu:源文件路径 /etc/apt/sources.list 和 /etc/apt/sources.list.d/

安装扩展源(CentOS):sudo yum install -y epel-release

2. 编辑器 Vim

2.1 三种核心模式

命令模式 (Normal mode):默认进入,用于控制光标、删除、复制、切换模式。

插入模式 (Insert mode):用于输入文字,按 Esc 回到命令模式。

底行模式 (Last line mode):用于保存、退出、查找、替换,按 Shift + ; 进入。

2.2 模式切换

命令模式 → 插入模式:i (光标前) / a (光标后) / o (下一行)

插入模式 → 命令模式:Esc

命令模式 → 底行模式:Shift + ; (输入 :)

2.3 命令模式常用命令

光标移动

h/j/k/l 左/下/上/右移一格

G 跳转到文件末尾

gg 跳转到文件开头

$ 跳转到行尾

^ 跳转到行首

w 跳转到下一个单词开头

b 跳转到上一个单词开头

n\]G 跳转到第 n 行(如 15G) #### 文本操作 x 删除光标后一个字符 X 删除光标前一个字符 dd 删除当前行 \[n\]dd 删除 n 行 yy 复制当前行 \[n\]yy 复制 n 行 p 粘贴复制的内容 u 撤销上一步操作 Ctrl + r 恢复撤销 r 替换单个字符 R 持续替换直到 Esc ### 2.4 底行模式常用命令 :w 保存文件 :q 退出 Vim :wq 保存并退出 :q! 强制退出(不保存) :set nu 显示行号 :\[n\] 跳转到第 n 行(如 :15) /keyword 向后查找关键字 ; ?keyword 向前查找 ; n 查找下一个 ### 2.5 Vim 配置 系统配置:/etc/vimrc 用户私有配置:\~/.vimrc 常用配置项: ```bash syntax on " 语法高亮 set nu " 显示行号 set shiftwidth=4 " 缩进为4个空格 ``` 常用插件:TagList、WinManager(用于文件浏览和函数列表) ## 3. 编译器 gcc/g++ ### 3.1 编译流程(4 阶段) 1. 预处理:宏替换、去注释、头文件展开、条件编译 → .i 文件 2. 编译:生成汇编语言 → .s 文件 3. 汇编:生成机器码 → .o 目标文件 4. 链接:生成可执行文件或库文件 ### 3.2 核心编译选项 |-----------------|----------------------|-------------------------------------| | 选项 | 作用 | 示例 | | -E | 仅预处理,生成 .i 文件 | gcc -E hello.c -o hello.i | | -S | 编译到汇编,生成 .s 文件 | gcc -S hello.i -o hello.s | | -c | 汇编到目标代码,生成 .o 文件 | gcc -c hello.s -o hello.o | | -o | 指定输出文件名 | gcc hello.o -o hello | | -g | 生成调试信息(供 gdb 使用) | gcc -g hello.c -o hello | | -static | 静态链接(将库代码打包进可执行文件) | gcc -static hello.c -o hello_static | | -shared | 动态链接(默认,依赖系统动态库) | gcc -shared hello.c -o libhello.so | | -O0/-O1/-O2/-O3 | 优化级别(O0 无优化,O3 最高优化) | gcc -O2 hello.c -o hello | | -Wall | 生成所有警告信息 | gcc -Wall hello.c -o hello | | -w | 不生成任何警告信息 | gcc -w hello.c -o hello | ### 3.3 静态链接 vs 动态链接 静态链接: 优点:运行时不依赖系统库,可移植性强,运行速度快 缺点:可执行文件体积大,库更新后需重新编译 动态链接: 优点:可执行文件体积小,库更新无需重新编译 缺点:运行时依赖系统动态库,移植性稍差 库文件后缀: Linux:静态库 .a,动态库 .so Windows:静态库 .lib,动态库 .dll 查看依赖库:ldd hello(查看可执行文件依赖的动态库) ### 3.4 静态库安装(CentOS) ```bash sudo yum install glibc-static libstdc++-static -y ``` ## 4. 自动化构建 make/Makefile ### 4.1 核心概念 make:命令工具,解释 Makefile 中的规则,实现自动化编译。 Makefile:文本文件,定义文件依赖关系和编译命令。 优势:一次编写,多次使用,自动判断哪些文件需要重新编译,提升开发效率。 ### 4.2 基础 Makefile 示例 ```bash # 目标文件: 依赖文件 myproc:myproc.c gcc -o myproc myproc.c # 注意:命令前必须是 Tab 键,不能是空格 .PHONY:clean # 声明 clean 为伪目标 clean: rm -f myproc ``` 依赖关系:myproc 依赖 myproc.c,若 myproc.c 比 myproc 新,则重新编译。 伪目标 .PHONY:避免和同名文件冲突,确保 make clean 总是执行。 ### 4.3 多阶段依赖推导 ```bash myproc:myproc.o gcc myproc.o -o myproc myproc.o:myproc.s gcc -c myproc.s -o myproc.o myproc.s:myproc.i gcc -S myproc.i -o myproc.s myproc.i:myproc.c gcc -E myproc.c -o myproc.i .PHONY:clean clean: rm -f *.i *.s *.o myproc ``` make 会递归查找依赖,从 .c 开始,依次生成 .i → .s → .o → 可执行文件。 ### 4.4 高级 Makefile 语法(变量与通配) ```bash # 定义变量 BIN=proc.exe CC=gcc SRC=$(wildcard *.c) # 获取当前目录所有 .c 文件 OBJ=$(SRC:.c=.o) # 将 .c 替换为 .o,生成目标文件列表 LFLAGS=-o FLAGS=-c RM=rm -f # 生成可执行文件 $(BIN):$(OBJ) $(CC) $(LFLAGS) $@ $^ # $@=目标文件名, $^=所有依赖文件 @echo "linking ... $^ to $@" # 模式规则:生成所有 .o 文件 %.o:%.c $(CC) $(FLAGS) $< -o $@ # $<=第一个依赖文件 @echo "compling ... $< to $@" .PHONY:clean test clean: $(RM) $(OBJ) $(BIN) test: @echo $(SRC) @echo $(OBJ) ``` ### 4.5 make 工作原理 1. 查找当前目录下的 Makefile 或 makefile。 2. 以第一个目标文件为最终目标。 3. 递归检查依赖文件的修改时间,判断是否需要重新编译。 4. 若依赖文件不存在,先生成依赖文件。 5. 执行编译命令生成最终目标。 ## 5. Linux 系统程序:进度条与行缓冲区 ### 5.1 行缓冲区现象 带 \\n 的 printf:printf("hello bite!\\n"); → 立即输出(\\n 刷新缓冲区)。 不带 \\n 的 printf:printf("hello bite!"); → 缓冲区满或程序结束才输出。 手动刷新缓冲区:fflush(stdout); → 强制输出缓冲区内容。 ### 5.2 倒计时程序示例 ```cpp #include #include int main() { int i = 10; while(i >= 0) { printf("%-2d\r", i); // \r 回车不换行,覆盖当前行 fflush(stdout); // 强制刷新 i--; sleep(1); } printf("\n"); return 0; } ``` ### 5.3 进度条完整代码 #### process.h ```cpp #pragma once #include void process_v1(); void FlushProcess(double total, double current); ``` #### process.c ```cpp #include "process.h" #include #include #define NUM 101 #define STYLE '=' // 版本1:简单进度条 void process_v1() { char buffer[NUM]; memset(buffer, 0, sizeof(buffer)); const char *lable="|/-\\"; int len = strlen(lable); int cnt = 0; while(cnt <= 100) { printf("[%-100s][%d%%][%c]\r", buffer, cnt, lable[cnt%len]); fflush(stdout); buffer[cnt] = STYLE; cnt++; usleep(50000); } printf("\n"); } // 版本2:可传参进度条 void FlushProcess(double total, double current) { char buffer[NUM]; memset(buffer, 0, sizeof(buffer)); const char *lable="|/-\\"; int len = strlen(lable); static int cnt = 0; int num = (int)(current*100/total); int i = 0; for(; i < num; i++) { buffer[i] = STYLE; } double rate = current/total; cnt %= len; printf("[%-100s][%.1f%%][%c]\r", buffer, rate*100, lable[cnt]); cnt++; fflush(stdout); } ``` #### main.c ```cpp #include "process.h" #include #include double total = 1024.0; double speed = 1.0; void DownLoad() { double current = 0; while(current <= total) { FlushProcess(total, current); usleep(30000); // 模拟下载耗时 current += speed; } printf("\ndownload %.2lfMB Done\n", current); } int main() { DownLoad(); return 0; } ``` #### Makefile ```bash SRC=$(wildcard *.c) OBJ=$(SRC:.c=.o) BIN=processbar $(BIN):$(OBJ) gcc -o $@ $^ %.o:%.c gcc -c $< .PHONY:clean clean: rm -f $(OBJ) $(BIN) ``` ## 6. 版本控制器 Git ### 6.1 核心概念 版本控制:记录文件每次修改,可回退到历史版本,支持多人协作。 Git:分布式版本控制系统,适合管理大型项目和非线性开发。 ### 6.2 安装 Git ```bash # CentOS yum install git # Ubuntu sudo apt install git # 验证版本 git --version ``` ### 6.3 GitHub 项目创建 1. 注册 GitHub 账号并登录。 2. 点击 New repository 创建新项目。 3. 填写项目名称、描述,选择公开/私有,点击 Create repository。 4. 复制项目链接(HTTPS/SSH)。 ### 6.4 核心操作(三板斧) 1. 克隆项目到本地:git clone \[项目URL

  1. 添加文件到暂存区:
    git add [文件名] # 添加单个文件
    git add . # 添加当前目录所有文件

  2. 提交到本地仓库:git commit -m "提交日志(描述本次修改)"

  3. 推送到远程仓库:git push

6.5 其他常用命令

git status:查看文件状态

git log:查看提交历史

git pull:拉取远程仓库最新代码

.gitignore:指定不需要 Git 管理的文件(如日志、临时文件)

配置用户信息:

bash 复制代码
git config --global user.name "Your Name"
git config --global user.email "you@example.com"

7. 调试器 gdb/cgdb

7.1 编译调试版程序

必须添加 -g 选项生成调试信息:

bash 复制代码
gcc -g mycmd.c -o mycmd  # 生成带调试信息的可执行文件

7.2 启动与退出 gdb

bash 复制代码
gdb [可执行文件名]  # 启动 gdb
Ctrl + d 或 quit    # 退出 gdb

7.3 核心调试命令

|--------------|-------------|------------------------|
| 命令 | 作用 | 示例 |
| list/l | 显示源码 | l main / l 10 |
| run/r | 运行程序 | r |
| next/n | 单步执行(不进入函数) | n |
| step/s | 单步执行(进入函数) | s |
| break/b | 设置断点 | b 24 / b main |
| info break/b | 查看断点信息 | info b |
| print/p | 打印变量/表达式 | p result / p start+end |
| set var | 修改变量值 | set var flag=1 |
| continue/c | 继续执行 | c |
| finish | 执行到函数返回 | finish |
| backtrace/bt | 查看函数调用栈 | bt |
| until | 执行到指定行 | until 14 |
| watch | 监视变量变化 | watch result |

7.4 调试技巧

watch 变量:当变量值变化时,gdb 会暂停程序并提示,适合排查变量被意外修改的问题。

set var 修改变量:在调试时临时改变变量值,验证问题原因。

cgdb:带界面的 gdb,更直观查看代码和调试信息,安装命令:

bash 复制代码
# Ubuntu
sudo apt-get install -y cgdb
# CentOS
sudo yum install -y cgdb

7.5 调试示例(排查结果为 0 的问题)

cpp 复制代码
// mycmd.c
#include <stdio.h>

int flag = 0;  // 错误:flag 初始为 0
int Sum(int s, int e)
{
    int result = 0;
    for(int i = s; i <= e; i++)
    {
        result += i;
    }
    return result*flag;  // 导致结果为 0
}

int main()
{
    int start = 1;
    int end = 100;
    int n = Sum(start, end);
    printf("result: %d\n", n);
    return 0;
}

调试步骤:

  1. gdb mycmd 启动调试。

  2. b 24 在 int n = Sum(start, end); 处设置断点。

  3. r 运行程序,触发断点。

  4. s 进入 Sum 函数,n 单步执行,p result 查看累加结果。

  5. p flag 发现 flag=0,set var flag=1 修改后,c 继续执行,结果恢复正常。

8. 补充知识点

条件编译应用场景:根据不同平台/环境编译不同代码(如 #ifdef linux)。

为什么要把语言变成汇编:汇编是机器码的文本表示,是 CPU 能直接执行的指令集,编译器将高级语言翻译成汇编,再转为机器码。

编译器自举:用编译器本身编译自己的源码,证明编译器能正确处理自身代码,是编译器成熟的标志。

9. 回车与换行

回车 \r:光标回到行首,不换行(老式打字机的"回车"动作)。

换行 \n:光标移到下一行(老式打字机的"换行"动作)。

Windows:\r\n 表示换行;Linux/macOS:\n 表示换行。


掌握这些Linux开发工具与核心知识点,不仅能搭建起高效的开发环境,更能帮你理解程序从编写到运行的完整逻辑,为后续系统编程与项目开发打下扎实根基。

相关推荐
旺仔.2912 小时前
容器适配器:stack栈 、queue队列、priority queue优先级队列、bitset位图 详解
c++
2501_926978333 小时前
AI的三次起落发展分析,及未来预测----理论5.0的应用
人工智能·经验分享·笔记·ai写作·agi
刘景贤3 小时前
C/C++开发环境
开发语言·c++
似水এ᭄往昔4 小时前
【Linux】gdb的使用
linux·运维·服务器
优雅的造轮狮4 小时前
WSL2 Docker Desktop配置优化及迁移D盘指南
运维·docker·容器
tian_jiangnan4 小时前
grafana白皮书
linux·服务器·grafana
大师影视解说4 小时前
基于Web端的AI电影解说自动化生产工具实测:4步完成从文案到成片的全流程
运维·人工智能·自动化·影视解说·电影解说工具·网页版电影解说·ai电影解说
mizuhokaga5 小时前
Linux内网集群基于Docker 安装 Chat2DB
linux·运维·docker
科士威传动5 小时前
微型导轨从精密制造到智能集成的跨越
大数据·运维·科技·机器人·自动化·制造