yum
yum就像手机上的应用商店,而给Linux提供各种软件以及软件维护的人还有服务器供我们下载的那帮人是受什么驱使的呢?Linux的社区已是为了提供一个技术讨论交流的平台,同时也是为了让依赖这些软件的个人和公司找到组织,一旦找到组织之后,这些依赖给软件的群体自然会为这些软件的开发群体提供帮助让你们可以生存下去。开源也有自己的生态,他们希望的就是自己的软件尽快影响全世界,由于是不收费的原因可以迅速占领市场,占领了市场之后这些依赖这些软件的群体是希望我能继续维护这些软件的,所以会进行捐赠等等帮助。
yum list | grep sl/yum search sl:搜索软件,建议采用前者搜索。
sudo yum install sl.x86_64 -y:一般建议以root身份安装软件,-y不再进行交互,直接进行安装就可以了。
sudo yum remove sl.x86_64 -y:一般建议以root身份卸载软件
软件源分成官方的软件和扩展的软件
yum这么知道去我要下载的软件在哪里?yum有自己的配置文件——yum源,yum会根据配置文件所指定的地址去搜素特定的软件。更换yum源(如果采用的是国外的镜像源,可以选择更新为国内的)
1.先进行备份老的yum源:Centos-Base.repo
2.wget获取新的yum源的配置文件
3.将下载的yum源重命名为Centos-Base.repo
4.yum clean all(清理曾今的缓存)&& yum makecache(并生成新的缓存)
如果想安装的软件找不到,有可能就是在扩展的yum源中:epel.repo。sudo yum install -y epel-release是根据你的base yum源,帮我们找到和它匹配的扩展yum源。
vim(文本编辑器)
vim是一款多模式的编辑器(多模式:代表每种模式存在各自的用法和区别,而且模式之间可以实现切换)。vim是一个单纯的编辑器,并不是IDE。
如果不知道自己处在什么模式下,无脑Esc一定会退到命令模式下。
底行模式:
wq(写入并退出)/set nu(调出行号)/set nonu(去掉行号)
/wjj:搜索wjj,n可以对搜索的内容进行向下搜索
有时候我们不想退出vim但是还是想要执行指令,就在底行模式采用!+指令:vim会自动回退到命令行,然后执行指令,接下你按回车键就可以重新回到vim界面。
%s/hello/hello world/g:g是global全局的意思,就是将全局的hello全部替换成hello world。
vs test.h:生成一个test.h文件,并且是分屏显示如下。
ctrl+w+w:切换光标到不同的窗口
命令模式:
yy/nyy(复制光标当前所在行或者复制当前行在内的若干行)
p/np(粘贴一行或者多行相同的内容到当前光标所在行之下)
u(撤销刚刚的操作)/ ctrl+r(对撤销进行撤销)
dd/ndd(对当前行、或者当前行在内的n行内容进行剪切,如果不进行p操作就相当于是删除指令)
shift+g(其实就是G,将光标定位到文档的结尾)
gg(将光标定位到文档最开始)
n+shift+g:将光标定位到文档第n行
shift+4(其实就是$符号):将光标定位到文档当前行的结尾
shift+6(其实就是^符号):将光标定位到文档当前行的开始
w、b:按照单词为单位,进行前后移动,w向后,b向前。也支持nw或者nb,一次移动n个单词
shift+~:快速大小写切换
r+x:替换光标所在的字符为x,nr+x就是将包含光标所在位置的连续n个字符替换成为x。
nx:删除包含光标所在位置的字符的连续n个字符。不加n是
n+shift+x(其实就是nX):删除包含光标所在位置的字符的连续n个字符,但是是向前删除。
hjkl:这四个键分别表示光标向左下上右侧一定
vim配置(涉及配置文件)
当vim启动的时候会自动的在当前用户目录下(当前用户目录就是/home/用户名)找配置文件,如果没有就是默认。在linux当中指令基本上只有一份,你安装之后其他的用户也可以使用,但是配置文件时一个用户一个,所以当前我们所做的vim配置不会影响其它用户。腾讯云关于vim的配置文件在根目录下的etc文件夹下面的vimrc文件。但是还有一种方法是自己配置.vimrc文件,注意.vimrc必须在当前用户目录下。我们可以用vim打开.vimrc文件并进行配置。注意:写c代码的时候禁止采用tab,因为有的解释器对于tab是四个空格而有的确实两个空格。
还有一种方法就是自动化配置,直接在命令行中执行命令:curl -sLf https://
gitee.com/HGtz2222/VimForCpp/raw/master/install.sh -o ./install.sh && bash ./install.sh,这段指令前面是获取一个安装脚本然后再执行该脚本的一个操作。 但是该指令只能再centos7.x下才可以成功配置。
gcc/g++
编译器就是将文本文件变成二进制的可执行文件
1、预处理(头文件展开、条件编译、宏替换、去注释等)
2、编译(c语言变成汇编语言)
3、汇编(形成可重定位的目标二进制文件obj,不可以被执行的,只是将我们自己的代码进行翻译形成二进制目标文件,到这个阶段为止没有引入任何其让人的代码,但是在我的代码里面由去调用库里面的函数)
4、链接(将自己代码形成的obj文件和对应的库文件链接起来,形成可执行程序)
-o:该选项后面紧跟的是我们要生成目标文件的名称当前用户目录下
gcc-E(从现在开始进行程序的翻译,预处理做完,就停下来) test.c -o myfile.i(默认-E之后是打印再屏幕上的,我们这边通过-o写入到myfile.i当中。
stdio.h头文件里面也包含了许多头文件,这么多头文件都要在预处理阶段进行展开,所以myfile.i文件会变得很大。预处理之后还是我们的c语言,并且myfile.i的注释已经被编译器裁掉了。#define M 10这行代码也已经不见了,但是M已经被替换了。而且条件编译也不见了,但是条件编译执行的结果保留下来了。
gcc -S test.c(myfile.i也可以) -o myfile.s(从现在开始进行程序翻译,当编译做完,就停下来)
gcc -c myfile.s(test.c也可以)-o myfile.o(将代码翻译成为二进制的目标文件)
gcc myfile.o -o myfile(执行链接过程)
动静态库
ldd:检测可执行程序形成的时候依赖那些库
我们为什么能够在linux下进行c、c++代码的编写和编译呢?
linux系统默认已经携带了语言级别的头文件和语言对应的库,一个语言被发明需要两种意义上的支持,一是必须要有配套的编译器解释形成二进制,而是语言必须要有跟该语言匹配的库,来提供语言层面的基础功能,比如说基础的io功能、容器等等。
动态库链接:将动态库对应的程序的地址拷贝到可执行程序当中,动态库可以理解成共享库,只需要一份就够了,其它的多个可执行程序都可以链接该共享库。
动态库负责对用户的程序进行动态链接,动态链接的时候找到动态库,拷贝动态库中的我所需要的代码的地址到我自己的可执行程序中相关的位置。动态链接成功,我们的程序还是依赖动态库,一旦动态库缺失,我们的程序百年无法运行。动态库因为可以被大家共享方法,所以真正的实现永远都是在库里,程序内部只有地址,比较节省空间。
静态库负责对用户的程序进行静态链接。静态链接的时候,找到静态库,拷贝静态库中我所需要的代码到我自己的可执行程序中。静态链接成功:我们的程序不依赖任何库,自己就可以独立运行。静态库因为自身拷贝的问题,比较浪费磁盘或者内存空间。
linux默认采用的是动态链接。一般的云服务器,默认只有动态库。 gcc test.c -o myfile-static -static(采用静态链接)。
make和makefile
make是一个命令,makefile是一个文件,处于当前源代码的路径下。make
makefile是一个围绕依赖关系和依赖方法构建的一个自动化编译的工具,make命令会自动帮我们取解析makefile内部相关的依赖关系和依赖方法形成可执行:
myfile:myfile.c//依赖关系,:左边的是目标文件,:右边的依赖文件。
gcc -o myfile myfile.c//依赖方法
.PHONY:clean//.PHONY是用来修饰目标文件clean,其含义是总是被执行的。比如make执行玩一次之后,再次执行make指令会报错myfile is up to date也就是make指令并非是总是被执行的,但是make clean可以连续多次执行。之所以make myfile不被设置成总是被执行的,是因为重新编译的代价太大了。每次编译的时候理论上只需要把重新修改过的文件拿过来进行编译然后链接起来就可以了。make是通过对比源代码和可执行程序的最近修改时间来判断是否需要进行重新执行,所以如果你修改了源代码之后可以再一次进行make编译。
clean://依赖关系中,目标文件对应的依赖文件列表可以是空。
rm -f myfile// 依赖方法既然可以支持执行gcc命令,那么执行其它的命令也是可以的。
为什么清理文件的时候要输入make clean而不能仅仅只是make?
make命令默认只会执行makefile的第一组依赖关系和依赖方法,只不过生成myfile文件的代码在最上面,所以执行的时候不用带上目标文件的名称直接make执行,我们也可以带上具体名称make myfile。此时如果将makefile文件里面的clean放在myfile的前秒你,make指令之默认执行的就是删除操作了。
sudo权限增加
行缓存区
c语言中有很多字符,宏观上可以分为可显字符和控制字符
\r:回车,单纯的返回到该行的最开始部分。\n:换行。c语言范畴把\n解释成了换行+回车两个动作。
上面代码的现象给人的感觉是先执行的sleep再执行的printf。但是实际上肯定是先执行的printf再执行的sleep,只不过是再sleep3秒的期间hello wjj没有被刷新罢了。既然没有被刷新,最后又被打印出来了,说明也没有被丢弃,那么在这3秒期间hello wjj一定被保存起来了,保存再缓冲区。接下来的问题就是这缓冲区在哪里?缓冲区什么时候刷新?为什么提供缓冲区?缓冲区是谁来申请的?
为什么带了\n数据就显示出来了呢?首先任何数据不管你是否带\n数据都会被保存在缓冲区里,而缓冲区有自己的刷新策略,\n会立马刷新缓冲区,刷新之后数据才会显示出来,但是刷新的同时也会清空缓冲区的数据。
#include <stdio.h> #include <unistd.h> int main() { int i = 10;//i从10开始和从9开始是完全不一样的现象。首先我们需要认识到凡是往显示器上打印的所有内容,都是字符。printf底层实现是先把数字i获取,将获取的数字全部转换成为字符串,然后遍历字符串一个一个的用putc显示出来。 for(; i >= 0; i--) { printf("%2d\r", i);//如果这边不做处理直接执行printf("%d\r", i)的现象就是打印10、90、80···。因为第一次大的是两个字符10,未来打9876的时候第二个字符都没有受到影响,因为只覆盖了第一个字符。带2d就相当于格式化预留出来两个字符的空间,这样的话打印一个字符的时候也会将第二个字符的位置覆盖掉。 fflush(stdout); sleep(1); } printf("\n"); return 0; }
一个小demo
//main.c 文件
#include "proc.h"
int main()
{
process();
return 0;
}
//proc.c文件
#include "proc.h"
#include <string.h>
#include <unistd.h>
#define SIZE 102//100个=加上一个>再加上一个\0
#define STYLE '='
#define ARR '>'
void process()
{
const char *lable = "|/-\\";
char bar[SIZE];
memset(bar, '\0', sizeof(bar));//直接全部添加成为\0,然后后面的操作是将\0替换成#即可。
int i = 0;
while( i <= 100 )//进度条既有0%也有100%,多以进度条要循环101次
{
printf("[%-100s][%d%%][%c]\r", bar, i, lable[i%4]);//%100s开100个字符的空间并且默认就是右对,而%-100s是左对齐。%%会被读成%。
fflush(stdout);//不加刷新函数,\r也不会刷新,所以数据直接都存放在缓冲区。
bar[i++] = STYLE;
if(i != 100) bar[i] = ARR;
usleep(100000);
}
printf("\n");//防止命令行覆盖了进度条
}
//proc.h文件
#pragma once
#include <stdio.h>
extern void process();
//makefile文件
myprocess:main.c proc.c
gcc -o myprocess main.c proc.c -std=c99//这边在编译的过程中头文件是要考虑的,但是这次的情况头文件就在当前的路径下,所以gcc编译器可以直接找到你需要的头文件。-std=c99是指用c99的标准来进行编译。
.PHONY:clean
clean:
rm -f myprocess
git
git是做版本管理的,远端仓库gitee就是把.git仓库做了一个可视化解释。
git clone HTTPS地址:将远端仓库克隆到本地
git add .:当前目录所有没有添加的文件
git commit -m "linux工具代码等等相关信,这些信息要好好写,写清楚这次提交做了哪些工作进行了哪些修改,方便后面回顾的时候根据这些信息了解代码的相关内容":把对应修改 的内容提交到本地仓库
git push:将代码推送到远端git log:可以查看所有的提交纪录
git rm 'main.c':删除main.c的文件
git status:查看本地和远端的之间同步的状态
将删除main.c提交到远端还是三板斧:git add . git commit -m "删除不需要的main.c文件“ git push
gdb
gdb调试器的核心工作就是定位问题的位置。所有的查看内容的指令比如说p、l都不会影响实际的调试指令。
gcc、g++默认生成的可执行程序是release版本,不是debug版本,所以会出先上图的错误。
解决方法 gcc test.c -g -o myfile:-g就是让gcc或者g++。release版本是没有调试信息的。所以器可执行程序的体积要比debug要小一些。
gdb myfile进入到调试:
l:展示代码 ,可以连续输入l就会接着展示后续的代码
l n:从第n行开始展示代码
l main:将main代码剧中展示
r:相当于F5直接运行代码,有断点运行到断点处
b n/b test.c:n:只有一个文件可以不用指定文件名,当有多个文件时需要指定文件名的第n行打断点
b test.c:main:通过文件名加上函数名来进行打断点
info b:查看断点,每一个断点都有自己的编号Num可以在该指令下查看到。该指令还可以看到断点Enb属性,是用来表示当前断点是否是空断点。
delete/d Num:Num是断点的编号,d 1就是删除编号为1的断点。删除断点不可以采用行号,只能采用断点编号。delete breakpoints:删除所有断点
disable breakpoint 1:是编号为1的断点为空断点,也就是保留断点的痕迹但是不具有断点的功能。也就是将编号为1的断点的Enb属性设置为n。enable breakpoint 1 :就是将编号1的断点的Enb属性设置为y,也就是正常断点。
逐过程是以函数为单位不进入函数。而逐语句是有函数就会进入到函数。而在gdb当中逐过程是next指令
回车:gdb会自动记录你最近的一条指令,按回车键就会自动执行。
step/s指令:逐语句。
breaktrace/bt:查看函数的调用过程,不如main函数调用a函数,a函数调用b函数,b函数调用c函数。按照栈空间的逻辑及逆行排列,比如说main函数在栈底,c函数在栈顶。
print/p xxx:查看xxx变量的值
print/p &xxx:查看xxx变量的地址
display xxx:查看xxx变量的值并常显示
undisplay num:num是变量的编号,该指令就是取消编号为num的变量的常显示。
until n:在函数内进行指定位置跳转,执行完区间代码。这个代码可以用来跳过多次循环。
finish: 当前处于某一个函数内,执行finish指令就可以只执行完该函数,就停下来。
continue/c:从当前断点直接运行至 下一个断点
set var i = 100:设置一个变量i的值,仅仅只是在某一个代码片段当中当i为多少值时运行结果是否正确。比如说for循环i从0一直加到100,输入该指令之后在通过p i指令查看i的值,i值已经执行到为100的时候了。
quie:退出调试