文章目录
前言
一、Linux(Centos 7.6)安装软件
1.1 源代码安装(不推荐)
方法:下载程序的源代码,并进行编译,就能得到可执行程序了。
1.2 rpm安装(不推荐)
将常用的软件的源代码提前编译好,做成软件包放在一个服务器上,通过包管理器就可以获取到这个编译好的软件包就可以进行安装了。
但是要注意的是这个软件包可能存在某种依赖关系(还要下载其他的软件包)。
1.3 yun安装 (推荐)
1.3.1 如何理解yum安装软件
yum是Linux下常用的一种包管理器。
它可以解决安装源,安装版本以及安装依赖的问题,使得我们使用的时候不用去关心这个软件包的一系列的问题,它自动帮助我们下载到最适合我们机器的软件包。
1.3.2 查看当前面环境支持的软件包
yum list | grep lrzsz
1.3.2 如何使用yum安装软件
注意:
1.关于 yum 的所有操作必须保证主机(虚拟机)网络畅通!!!
2. 一般需要sudo或者root账户下才能完成
示例:
yum install -y lrzsz
完成安装:
1.3.4 如何卸载软件
//举个例子, 卸载lrzsz这个软件
yum remove lrzsz
1.4 总结与思考
在Linux环境下,一般推荐yum下载软件,yum其实是一个包管理器。它怎么知道软件该去那里下载呢?
1.4.1 yum怎么知道去那里找下载的软件包?
Linux环境中有官方配置的yum源。
它在:
//绝对路径
/etc/yum.repos.d
在这个路径中有个文件是CentOS-Base.repo,这个文件就存放了官方认可的yum源。
我们打开文件可以看到一部分的下载链接。yum安装软件时,就会在这些链接中找。
除了官方yum源,还可以安装扩展yum源。
//安装扩展源
yum install -y epel-release
二、Linux编辑器-vim
vim是一个多模式的编译器,主要用于代码编写。
2.1 vim的简单配置
演示一下如何配置:
在 shell 中执行指令(想在哪个用户下让vim配置生效, 就在哪个用户下执行这个指令. 强烈 “不推荐” 直接在 root 下执行):
curl -sLf https://gitee.com/HGtz2222/VimForCpp/raw/master/install.sh -o ./install.sh && bash ./install.sh
插件下载完成后,输入“source ~/.bashrc”或者重启xshell就能使用配置好的vim了
2.2 vim常用的三种模式
三种模式之间的转换方式:
2.2.1 命令模式
- gg:定位光标到文本最开始的位置。
- shift+g(G):定位光标到文本结尾的位置。
- n+shift+g(nG):定位光标到文本的第n行。
- (n) yy:复制光标所在行(n行)。
- (n)p:粘贴(n重复行)到光标所在的下一行。
- u:撤销,对撤销后悔:ctrl+r。
- (n) dd:剪切、删除\
- shift+^:定位光标到当前行的开始。
- shift+$:定位光标到当前行的结尾。
- w、b:光标安装单词进行行内跨行进行移动。
- h、j、k、l:左、下、上、右移动光标。
- shift+~:大小写转换
- (n)r:对光标之后的所有字符进行批量化替换。
- shift+r:切换为替换模式。
- (n)x:对光标字符之后的字符进行删除。
2.2.2 底行模式
- vs + 文件名:打开多个文件编辑窗口
- 在多文件编辑窗口中,ctrl+ww可以切换当前编辑文件。
- !wq:强制保存并退出当前编译文件。
- set (no)nu:(不)显示行号。
- !指令:不退出编译,指向指令
2.2.3 插入模式
在命令模式下输入i。进入插入模式,一般编译代码的模式。
2.3 vim的应用(将普通用户添加在sudoers file文件中)
作用:普通用户如果在这个文件中,这个普通用户就能用sudo+一条命令。这条命令就相当于是root执行的。
使用root账户,找到绝对路径为:/etc/sudoers
使用vim打开这个文件,找到大概100行的位置.
将100这行复制,粘贴到下一行,最后将root改为你想要添加的用户。
最后强制保存退出就可以了。
验证一下hzh这个用户是否可以执行sudo这个指令。
//使用sudo,touch一个文件
sudo touch tmp.c
如果这个文件的所有者是root,所属组也是root,就表示这个用户已经在sudoers这个文件中了。
三、Linux编译器 - gcc/g++
gcc和g++的使用方法(选项)基本是相同的。
这里只介绍gcc。
3.1 源文件如何转换成可执行程序
第一步:源文件通过预处理生成 后缀为.i的文件
第二步:后缀为.i的文件通过编译生成后缀为.s的文件
第三步:后缀为.s的文件通过汇编生成可被计算机识别的二进制文件,后缀为.o,也叫目标文件,在window平台下后缀为.obj。
第四步:将多个后缀为.o的文件通过链接生成可执行程序。
3.1.1 预处理
预处理功能主要包括:头文件展开、宏替换、去除注释和条件编译。
例如:让tmp.c进行预处理,完成后停下来
//选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程
gcc -E tmp.c -o tmp.i
在gcc命令行中也可以定义宏的。
gcc ... -D + 宏
3.1.2 编译
在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言
gcc -S tmp.c -o tmp.s
3.1.3 汇编
把编译阶段生成的".s"文件转成目标文件
生成目标文件不能单独运行,就算给它加上可执行权限,也不能运行。
//给tmp.o添加可执行权限
chmod +x tmp.o
//
gcc -c tmp.s -o tmp.o
查看tmp.o的内容。
3.1.4 连接
多个目标文件、头文件和库文件通过链接生成可执行程序。
gcc tmp.c -o tmp
3.2 为什么要链接
链接:自己写的代码+库 生成可执行程序
库提供了方法的实现,一般具体存在于某个目录文件下。库分为动态库和静态库,在Linux下动态库的后缀一般为.so,静态库的后缀是.a。
在window平台下,动态库的后缀为.dll,静态库的后缀为.lib。
库文件中包含了头文件和库文件。头文件提供了方法的声明,库文件提供了方法的实现。库文件也是c语言实现的,通过翻译打包生成的。它的作用让你写的代码经过翻译后能够被计算机翻译最后执行。
3.3 .o文件和库是如何链接?
3.3.1 动态链接
动态库一定存在某个目录下,可执行程序使用了这个动态库后,就相当于建立了某种依赖关系。如果缺失那么依赖这个动态库的可执行程序就无法执行了。
查看可执行程序的依赖的动态库
ldd 可执行程序
动态库的优点:由于动态库是共享库,它可以有效的节省内存空间、磁盘空间以及网络空间等。
3.3.2 静态链接
静态链接:将库文件的方法拷贝到目标程序中,拷贝后就不用依赖静态库了。但是它的体积多大,比动态库消耗资源静态链接的前提是当前环境中下载了静态库。如果没有可以输入下面的执行帮助你下载C语言的静态库。
//c语言
sudo yum intsall -y glibc-static
//c++
sudo yum install -y libstdc++-static
在Linux环境里,默认的就是动态链接,如果你像让可执行程序进行静态链接。需要添加 -static
3.4 Debug 和 Release
在编译可执行程序加-g,就会生成添加了调试信息的可执行程序,并且可以被追踪。如果不加就默认是Release版本。
这里补充一条指令:查看可执行程序的二进制构成
readelf -S + 可执行程序
四、make和makefile
4.1 make和makefile是什么?
make 是一条指令,makefile是当前目录下的一个文件。
makefile中可以写一些对应的依赖关系以及依赖方法。
make会自动推导makefile文件中的依赖关系。
来看下面代码帮助你来理解它们
//makefile文件中的内容
clean:
rm -f tmp.o tmp.s tmp.i tmp.i tmp
tmp:tmp.o
gcc -o tmp tmp.o
tmp.o:tmp.s
gcc -c tmp.s -o tmp.o
tmp.s:tmp.i
gcc -S tmp.i -o tmp.s
tmp.i:tmp.c
gcc -E tmp.c -o tmp.i
当你输入make指令时,make指令默认从makefile中自顶向下的找到第一条依赖关系,并执行对应的依赖方法。
你也可以明确makefile中的依赖方法。
这样make就不会执行gcc -o tmp tmp.o 这个依赖方法了。
4.2 make相关的问题
当makefile文件中内容是:
tmp:tmp.c
gcc -o tmp tmp.c
clean:
rm -rf tmp
输入make指令,默认执行的命令就是gcc -o tmp tmp.c这条命令。
输入第一次make时,可以执行这条命令,但后面输入make就不能执行了。这是因为提高编译的效率做的优化。通过比较可执行文件和源文件的最新修改时间就能知道是否需要执行命令。
结论:make会根据源文件和目标文件的新旧,判断是否需要重新执行依赖关系进行编译。
4.3 如何查看文件的时间属性
stat 文件名
文件 = 文件内容 + 文件属性
Access:最近一次对文件访问操作的时间。
Modify:最近一次只对文件内容修改时的时间。
Change:最近一次只对文件属性修改时的时间。
//将这个文件的Access、Modify和Change更新至最新时间
touch 一个已经存在的文件
4.4 如何总是让依赖关系执行
.PHONY:伪目标
这样每次make时,就能执行gcc -o tmp tmp.c这条命令了。
4.5 makefile中可以简化的内容
//$@代表冒号左侧的所有内容,$^代表冒号右侧的所有内容
tmp:tmp.c
gcc -o $@ $^
4.6 隐藏make回显的命令
默认情况执行make中依赖方法会显示执行的命令
如果想隐藏,在想隐藏的依赖方法前加@
例如:
五、开发工具的应用(进度条的实现)
5.1 回车换行和缓冲区的认识
回车换行其实是两个步骤;
回车:使光标回到当前行的起始位置。
换行:使光标定位到当前行的下一行的起始位置。
下面的代码帮助理解
#include<stdio.h>
#include<unistd.h>
int main()
{
printf("hello linux"); //1
sleep(2); //2
return 0;
}
将这段代码编译执行,它的运行现象:
1.向延迟2秒钟。
2.再打印hello linux
C语言在执行代码是从上往下依次执行的,但这里的结果却是相反的。
这是因为C语言中的缓冲区(由C语言维护的一段内存)的存在,hello linux被存放在了缓冲区。当程序执行结束后就被刷新出来了。
补充:
- C语言在运行一个程序(代码)。会默认打开三个输入输出流:标准输入(stdin)、标准输出(stdout)、标准错误(stderr)。
- 在linux下一切皆是文件,显示器也看作一个文件,C语言默认打开三个文件,其中标准输出就对应显示器,它的数据类型就是stdout(FILE*)。
- 强制刷新缓冲区的内容。fflush(stdout)。
#include<stdio.h>
#include<unistd.h>
int main()
{
printf("hello linux");
fflush(stdout);
sleep(2);
return 0;
}
5.2 倒计时的简单模拟
#include<stdio.h>
#include<unistd.h>
int main()
{
int n;
printf("请输入要倒计时的时间:");
scanf("%d", &n);
while(n >= 0)
{
printf("倒计时:%-2d\r", n);
fflush(stdout);
sleep(1);
n--;
}
printf("倒计时完成\n");
return 0;
}
5.3 进度条的模拟实现
首先:
创建三个文件:main.c 、processbar.c processbar.h
//processbar.h
#pragma once
#include <stdio.h>
#include <unistd.h>
extern void processbar();
//processbar.c
//在这个文件写实现进度条的代码
#include "processbar.h"
void processbar()
{
printf("processbar\n");
}
//main.c
#include "processbar.h"
int main()
{
processbar();
return 0;
}
5.3.1 进度条的实现
这是processbar.c文件的内容
#include "processbar.h"
// '\'需要转义
const char* label = "|/-\\";
void processbar()
{
char Str[MAX_NUM];
memset(Str, '\0', sizeof(Str));
int len = strlen(label);
int cnt = 0;
while(cnt <= 100)
{
//输出%时也需要转义,可以用'\'或者'%'
printf("[%-100s][%c][%d%%]\r", Str,label[cnt%len], cnt);
fflush(stdout);
Str[cnt++] = STYLE;
if(cnt < 100) Str[cnt] = STYLE_BOBY;
usleep(100000);
}
printf("\n");
}
这是processbar.h中文件的内容
#pragma once
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#define STYLE '-'
#define STYLE_BOBY '>'
#define MAX_NUM 102
extern void processbar();
运行结果:
QQ20231030-112239
5.3.2 模拟使用进度条
进度条如何使用?
当某种下载任务下载时,不断下载并将下载进度告诉进度条,进度条在回显进度,就可以使用了。
main.c中的内容
#include "processbar.h"
//callback_t 是一个函数指针
typedef void (*callback_t)(int);
//模拟某种下载任务,通过回调函数回显进度条的进度
void download(callback_t cb)
{
//模拟下载文件的总大小
int total = 1000;
//模拟当前下载完成的大小
int cur = 0;
while(cur <= total)
{
cb(cur*100 / total);
//模拟下载花费的时间
usleep(50000);
cur+=10;
fflush(stdout);
}
printf("\n");
}
int main()
{
printf("下载任务1: \n");
download(processbar);
initbar();
printf("下载任务2: \n");
download(processbar);
initbar();
printf("下载任务3: \n");
download(processbar);
initbar();
return 0;
}
processbar.c中的内容
#include "processbar.h"
const char* label = "|/-\\";
char bar[NUM] = {'\0'};
void processbar(int rate)
{
if(rate < 0 || rate > 100) return;
int len = strlen(label);
printf("[%-100s][%d%%][%c]\r", bar, rate, label[rate % len]);
bar[rate++]=STYLE;
if(rate < 100) bar[rate] = STYLE_BOBY;
}
void initbar()
{
memset(bar, '\0', sizeof(bar));
}
processBar.h中的内容
#pragma once
#define NUM 102
#define STYLE '='
#define STYLE_BOBY '>'
#include <stdio.h>
#include <unistd.h>
#include <string.h>
extern void processbar(int rate);
extern void initbar();
六、git的简单操作
首先你得有一个gitee的账号。
6.1 新建一个仓库
找到新建仓库
简单配置仓库:
找到新建的仓库中的克隆/下载:将HTTPS复制
6.2 将远端仓库的文件拷贝到本地仓库
在Linux环境上输入命令:
git clone + 刚刚复制HTTPS的内容
这样拷贝成功了。当然如果你是第一次使用这个git clone。可能需要输入对应的gitee账号和密码。依次输入就可以。
6.3 将本地仓库文件上传到远端仓库
再刚刚git clone 成功后,当前目录下多了一个test_git。我们进入这个目录中。
其中这个.git其实就是远端仓库。
6.3.1 git add .
作用:将当前没有添加到远端仓库的文件添加到暂存区里。
6.3.2 git commit -m “提交日志”
作用:将新加到暂存区文件推送到本地仓库。
6.3.3 git push
作用:将新添加到本地仓库的文件提交到远端仓库。
在执行这条命令时,可能需要输入你gitee的账号名称以及密码。
6.3.4 git log (查看提交信息)
截取一部分展示一下:
6.3.5 git status
查看当前是否有文件需要进行相关的操作,例如:是否有文件要被添加到远端仓库(并且显示对应的操作)
6.4 .gitignore文件
当你在上传文件时,不想将后缀为某个类型的文件上传到远端仓库。
可以在.gitignore文件中添加对应的后缀
例如:我在.gitignore文件中添加如下内容
# 不会将后缀为.txt .s .cxx 的文件上传至远端
# *和后缀之间不能有空格
*.txt
*.s
*.cxx
我创建了4个文件:test.c /test.txt/ test.s/test.cxx/test.cpp
在将它们提交到远端仓库后就只会得到test.c和test.cpp文件。
七、Linux的调试器:gdb
7.1 Debug和release
gcc默认是以release发布的。release版本没有调试信息并且不能调试。
如果要以Debug方式发布。在gcc编译时带-g选项。
7.2 开始调试和结束调试
开始调试:
//这个是可执行程序需要要有可调试信息
gdb 要调试的可执行程序
例如:
结束调试:直接输入q退出调试模式。
7.3 调试选项
7.3.1 查看代码
//显示第n行的代码,显示代码不一定从n开始。
// n为正整数
l n
示例:
补充:在gdb中,它会已经最近一次执行的命令。所有如果还想继续查看后面代码,直接按回车就可以查看了。
示例:
7.3.2 设置断点、删除断点以及查看断点信息
设置断点:
//方法1:
b + 行号
//方法2:
b + 指定文件:函数名
示例:
方法1:
方法2:
删除断点:
d 断点编号
示例:
查看断点信息:
info b
示例:
7.3.3 运行这个可执行程序
选项:r
如果没有断点,这个是可执行程序就会正常运行。如果有断点,在第一个断点停下来。
示例:
没有设置断点的情况:
有断点的情况:
7.3.4 逐过程和逐语句执行代码
逐过程:next 或者 n
不会跳转到函数内
逐语句:step 或者 s
会跳转到函数的内部。
7.3.5 常显示变量的值和取消显示
常显示变量的值
display 变量名
取消常显示
undisplay 变量名
示例:
7.3.5 让程序运行到指定的行
util 行号
示例:
7.3.6 让当前函数执行完
命令:finish
补充:在main函数中不生效。
示例:
7.3.7 断点的使能和不使能
设置该断点为不使能(该断点不生效):
disable 断点编号
设置该断点使能:
enable 断点编号
示例:
将断点1、2设为不使能。断点3为使能
现象:程序跳过断点1、2,在断点3停下来了。
7.3.8 查看当前函数栈帧的变量值
info locals
总结
Linux环境下的开发工具就介绍到这里,可能会有介绍不详细的地方,但希望帮助大家能够简单快速的使用这些工具。