基础编辑工具使用【Linux】

目录

[1 Linux下安装软件的常见方式](#1 Linux下安装软件的常见方式)

[2 Linux中 Vim 编辑器的使用](#2 Linux中 Vim 编辑器的使用)

[2.1 命令模式:](#2.1 命令模式:)

[2.2 插入模式:](#2.2 插入模式:)

[2.3 底行模式:](#2.3 底行模式:)

[3 Linux 编译器 gcc/g++的使用](#3 Linux 编译器 gcc/g++的使用)

[3.1 GCC 编译过程](#3.1 GCC 编译过程)

[4 Linux 项目自动化构建工具-make/Makefile](#4 Linux 项目自动化构建工具-make/Makefile)

[5 Linux小程序--进度条实现:](#5 Linux小程序--进度条实现:)

[5.1 前置小知识](#5.1 前置小知识)

[5.2 进度条实现](#5.2 进度条实现)

[6 Linux调试器-gdb使用](#6 Linux调试器-gdb使用)

[6.1 启动与退出调试](#6.1 启动与退出调试)

[6.2 查看源码](#6.2 查看源码)

[6.3 打断点](#6.3 打断点)

[6.4 查看所有断点](#6.4 查看所有断点)

[6.5 删除断点](#6.5 删除断点)

[6.6 禁用断点](#6.6 禁用断点)

[6.7 断点运行与调试](#6.7 断点运行与调试)

[6.8 变量监视](#6.8 变量监视)

[6.9 高级调试技巧](#6.9 高级调试技巧)


1 Linux下安装软件的常见方式

1.源代码安装

  1. rpm包安装

  2. 包管理器安装(推荐)

例如:手机上的应用商店就相当于 包管理器安装

2 Linux中 Vim 编辑器的使用

常用:

2.1 命令模式:

n + yy : 复制当前行 , n表示连续复制n行

n + p : 粘贴,当前光标的下一行,n表示把指定的内容粘贴n次

u : 撤销当前操作

ctlr+ r : 对历史u撤销进行撤销恢复

n + dd : 剪切/删除指定行,连续的多行

n + x : 删除光标后面的字符

n + X : 删除光标之前的字符

n + r + '字符 ': 表示对光标指定的位置,进行字符的替换,也可以替换多个

shift + r = R : 替换模式,直接进行文本替换

shift + ` = ~ : 大小写快速切换

shift+4 = $ : 把光标定位到 行的最结尾

shift+6 = ^ : 把光标移动到 行的最开头

n + gg : 把光标定位到文本的最开始, n表示定位到文本的第几行

shift + g = G :把光标定位到文本的最结尾

h , j k,l : 表示上下左右移动也可以带n

h: 表示光标往左移动

l : 光标往右移动

j : 光标往下移动

k : 光标往上移动

w : 表示按照单词为单位进行光标后移动

b : 表示按照单词为单位进行光标前移动

代码注释:

注释多行

① ctrl + v : 进入试图模式,h,j,k,l 进行区域选择

② shift + i = I 进入插入模式 输入//

③ esc 两次即可完成注释

取消注释:进入视图模式,区域选择,选中// ,d 即可去注释

2.2 插入模式:

a,i,o : 进入插入模式

2.3 底行模式:

set nu : 显示行号

set nonu : 不显示行号

s/原词/要替换的词/g

/关键字 : 搜索关键字

vs test.c 开启分屏窗口

ctrl + ww : 移动光标到另一个分屏窗口

vim 编辑器配置,cd ~ 后,vim .vimrc 中可以配置vim编辑器

3 Linux 编译器 gcc/g++的使用

3.1 GCC 编译过程

gcc 如何完成?

3.1.1 预处理:主要包括宏定义、去注释、文件包含、条件编译(动态代码裁剪)

预处理指令是以#号开头的代码行

示例:gcc -E hello.c -o hello.i

-E 指的是让gcc在预处理结束后停止编译过程

-o 指的是目标文件,.i文件表示已经过预处理的C原始程序

这里值得注意的是条件编译:

示例1:调试开关

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

#define DEBUG  // 如果这行有定义,则编译调试代码;如果注释掉,则不编译

int main() {
    int x = 10;
    #ifdef DEBUG
    printf("Debug: x = %d\n", x); // 只有DEBUG被定义时才编译
    #endif
    printf("Program running...\n"); // 总是编译
    return 0;
}

示例2:防止头文件重复包含

cpp 复制代码
// my_header.h
#ifndef MY_HEADER_H  // 如果没定义MY_HEADER_H
#define MY_HEADER_H  // 就定义它

// ... 头文件的内容(函数声明、类定义等)

#endif // MY_HEADER_H  // 结束条件编译

3.1.2 编译:检查代码的规范性以及是否有语法错误等,检查无误后把代码翻译成汇编语言。

示例:gcc -S hello.i -o hello.s

-S表示指进行编译不进行汇编,生成汇编代码(hello.s)

3.1.3 汇编:把编译完成的汇编文件汇编成目标文件

示例:gcc -c hello.s -o hello.o

-c表示汇编代码转化为.o的二进制目标代码

3.1.4 连接: 将各个独立的 .o 目标文件以及系统库文件(静态库或动态库)合并到一起。

主要工作是符号解析地址重定位,把未确定的函数调用地址填补正确,最终生成可执行文件。

示例:gcc hello.o -o hello

./可执行程序,./hello

链接库查询:ldd code.exe

我们经过预处理、编译、汇编和连接这一系列操作过于繁琐,所以接下来的自动化构建工具就能够帮助我们提高效率。

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

make是一个命令,makefile是一个文件

makefile/make会自动根据文件中的依赖关系,进行自动推导,帮助我们执行所有相关的依赖方法

简单例子:

vim makefile 进入:

gcc前面必须是 Tab 缩进,不能空格,否则 Makefile 报错。

使用例子:

自动推导:我们可以在makefile文件写入编译方法

这样写太繁琐了,下面方法比较方便:(推荐)

makefile也是支持变量的,使用变量:$(变量名) 或者 ${变量名}

例如,bin和src都是变量名

$@ 代表目标 (target) ,也就是冒号左边的那一项。 这里目标是 code.exe,所以 $@ = code.exe

$^ 代表所有依赖文件 ,冒号右边全部依赖。 这里依赖是code.c,所以$^ = code.c

等价于:gcc -o code.exe code.c

这里我们发现每次make的时候都会出现命令的打印,这里隐藏命令的方法是:

@放到依赖方法的前面,@依赖方法,例如:

例1:

运行结果:

例2:

可以适当接入一些提示输出echo等,依赖方法可以执行多行的

bash 复制代码
bin=code.exe
src=code.c
$(bin):$(src)
	@gcc -o $@ $^
	@echo "compiler $(src) to $(bin) ..."
	@echo "Compilation complete!"
	@echo "Run the program with ./code.exe"
.PHONY:clean
clean:
	@rm -f $(bin)
	@echo "clean project files ..."

运行结果:

5 Linux小程序--进度条实现:

5.1 前置小知识

5.1.1 关于回车

回车和换行:

'\n' 指的就是回车和换行两个动作

'\r'回车是到行头

下面: 有\n的是先打印然后再sleep 3秒

没有\n的是先sleep 3秒,然后再打印

这里涉及到缓冲区,缓冲区可以简单理解成一个块内存空间,程序结束时,一般要进行自动刷新缓冲区,'\n' 是进行刷新缓冲区(行刷新)

5.1.2 关于fflush

这里我们想要让光标一直回到刚开始的位置,例如就像倒计时打印,想要数字原地倒计时,就是让数字显示一下刷新一下(将缓冲区的数据强制刷新到屏幕)

值得注意的是:

这里倒计时打印,目前实现了回车,但是数字没有打印,这是因为C语言标准库中stdout输出默认是行缓冲模式,也就是说只有当遇到 '\n' 、强制刷新或者缓冲区满的时候才把内容输出到文件。(从Linux一切皆是文件的角度分析,也就是把内容强制写入到负责屏幕输出的文件里面)

所以这里的解决方法是使用强制刷新

fflush

通过man 手册查看fflush

复制代码
man fflush

所以我们给加上:

cpp 复制代码
fflush(stdout);

所以接下来直接进行使用底行模式进行运行程序:

在命令模式下,使用感叹号!调用系统命令来运行程序。

运行结果:

接下来实现进度条:

5.2 进度条实现

简单版:

使用一个存储101个字符的字符串用来存放'#',然后刷新并打印每次存放的字符串的情况

cpp 复制代码
#define Len 101
#define Style '#'
void TestBar()
{
	int n = 0;
	char Bar[Len];
	memset(Bar,'\0',sizeof(Bar));
	while(n <= 100 )
	{
		Bar[n] = Style;
		printf("[%-100s][%3d%%]\r",Bar,n);
		++n;
		fflush(stdout);
		usleep(100000);
	}
	printf("\n");

}

运行结果:

关于美化:可以100% 后面加入旋转的lable,| / - \

cpp 复制代码
#include"ProcessBar.h"

#define Len 101
#define Style '#'
void TestBar()
{
	int n = 0;
	char Bar[Len];
	memset(Bar,'\0',sizeof(Bar));
	const char* lable = "|/-\\";
	while(n <= 100 )
	{
		Bar[n] = Style;
		printf("[%-100s][%3d%%] [%c]\r",Bar,n,lable[n%4]);
		++n;
		fflush(stdout);
		usleep(100000);
	}
	printf("\n");

}

复杂版:

接下来我可能有这样的需求,当在多个文件的场景下,每个文件都有进度条

多个文件都有进度条

cpp 复制代码
#include "ProcessBar.h"



#define Style '#'
#define Len 101
const char* lable = "|/-\\";

void ProcBar(double total,double current)
{
	char Bar[Len];
	memset(Bar,'\0',sizeof(Bar));
	int len = strlen(lable);
	//compute the current rate
	double rate = (100.0*current)/total;
	int loop_count = (int)rate;
	int n = 0;
	while(n <= loop_count)
	{
		Bar[n++] = Style;
	}
	Print the download progress based on the amount of data downloaded each time
	fflush(stdout);
	usleep(100000);

}

优化:

彩色进度条

可以适当给printf加上打印的颜色

cpp 复制代码
printf("\033[32m[%-100s]\033[0m \033[33m%6.1lf%%\033[0m %c\r",Bar,rate,lable[n%len]);

6 Linux调试器-gdb使用

在linux命令行里面进行调试,通常可以使用gdb进行调试,平时使用的 gcc -o test test.c 指的编译程序一般编译的是release模式下,但是我们需要进行程序的调试,所以需要去编译debug模式下的程序。

一般情况下,编译器形成可执行程序的时候,会调试信息,在gcc/g++让debug模式编译 -g

bash 复制代码
gcc -o test-debug test.c -g

我们发现debug的可执行程序的文件的大小确实比release模式下大

同时也可以 把可执行程序的符号表读出,这里可以把debug信息筛选出

bash 复制代码
 readelf -S test-debug | grep debug

6.1 启动与退出调试

gdb 可执行程序 进入调试,按q可以退出

注意这里的可行程序是debug模式下的

6.2 查看源码

gdb下查看文件内容

list 文件名:行号

6.3 打断点

调试程序跑起来需要先打断点,再run

打断点,可以使用b 文件名:行号/函数名

6.4 查看所有断点

我们知道在VS里面都会有红色的断点显示

在gdb中使用info b用来显示当前打的断点 (打断点的意思就是在调试程序的某个地方停下来)

6.5 删除断点

删除断点需要参考info b 列表前面的编号

d 断点编号

6.6 禁用断点

与删除断点不同,当我们打完断点后,我们像保留这个位置的断点,但是又不想先去直接使用这

个断点,所以说像给禁用一下 :disable 断点编号,使能断点由y变成n

我又想使能之前禁用的断点

enable 禁用的断点编号

6.7 断点运行与调试

运行调试程序

打完断点后 run即可

我们还知道调试可以 逐过程和逐语句,gdb逐过程输入n(next)

gdb逐语句输入s(step)

6.8 变量监视

gdb 查看监视窗口的变量

p 变量内容/地址

监视多个变量

display 变量

取消某个常显示变量

undisplay 常显示的编号

6.9 高级调试技巧

c(continue)运行到下一个断点处

当我们进入某函数里面进行调试,函数循环,我们想进行逐函数执行

finish 完成所在函数的执行

until 行号 : 跳转到指定行,中间代码都是运行完成的

info local :查看函数中的临时变量的值

set var :修改变量的值

bt: 查看当前栈帧局部变量的值

相关推荐
Tinyundg43 分钟前
关于Termux的基本使用——安卓手机爆改Linux服务器?
linux·运维·服务器·智能手机·个人开发
g10565591391 小时前
华为 OceanStor 基础使用入门指南
服务器·数据库·性能优化
鱼很腾apoc1 小时前
【Linux】第15期 讲解IP网络层核心原理与机制
linux·服务器·网络协议·学习·tcp/ip·ip·网络层
zx_741484811 小时前
【Linux入门】常用基本命令(一)——帮助、文件目录操作、时间日期与用户组管理
linux·服务器
AugustSkys1 小时前
PostgreSQL 完全指南:特性对比 + 安装部署 + 配置管理 + psql 实战 + pgAdmin 图形化
运维·postgresql·开源数据库·pgadmin
AutumnWind04201 小时前
【Shell 知识速查表】
linux
风哥2号1 小时前
数据库教程FGMT04‑生产环境Linux+Oracle19c RAC集群安装配置与项目实战
linux·数据库
qetfw1 小时前
Debian Postfix + Dovecot 基础配置:DNS、Maildir、IMAP 与邮件队列验证
linux·服务器·网络·debian
weixin_446260851 小时前
PromptMatic:通过多阶段提示优化提升大模型的指令遵循能力
运维·服务器