4.基础开发工具

一、Linux中安装软件

1)源码安装

2)软件包安装---rpm

3)包管理器yum(centos)  apt/aptget(ubuntu)

a.网络下载

b.安装(就是拷贝)必须使用root权限

安装到系统里,只安装一次,任何人都能使用。

包管理器会自动给我们解决包的依赖问题。

什么是包管理器?

类似手机上的应用商店。

软件是由谁提供的?

理解过程:操作系统背后的配套软件,也是生态的一环。

我的机器怎么知道下载链接?

操作系统内部,内置链接,由于原因,国内有镜像源。

base---稳定软件

epel---扩展软件源

开源本质是一种商业模式。

修改yum源

/etc/yum.repos.d/*(yum源配置文件)

Cetnos 安装源路径:
-rw-r--r-- 1 root root 676 Oct 8 20:47 CentOS-Base.repo # 标准源
-rw-r--r-- 1 root root 230 Aug 27 10:31 epel.repo # 扩展源

yum install -y epel-realse(安装epel扩展软件源)

查看软件包
通过 yum list 命令可以罗列出当前⼀共有哪些软件包. 由于包的数目可能非常之多, 这里我们需要使用grep命令只筛选出我们关注的包。
例如: yum list | grep lrzsz
卸载软件
yum remove [-y] lrzsz

易错点1:

        死代码删除是编译最优化技术,指的是移除根本执行不到的代码,或者对程序运行结果没有影响的代码,而并不是删除被注释的代码。

        内联函数,也叫编译时期展开函数, 指的是建议编译器将内联函数体插入并取代每一处调用函数的地方,从而节省函数调用带来的成本,使用方式类似于宏,但是与宏不同的是内联函数拥有参数类型的校验,以及调试信息,而宏只是文本替换而已

        for循环的循环控制变量,通常被cpu访问频繁,因此如果调度到寄存器中进行访问则不用每次从内存中取出数据,可以提高访问效率。

        强度削弱是指执行时间较短的指令等价的替代执行时间较长的指令,比如 num % 128 与 num & 127 相较,则明显&127更加轻量。

易错点2:

编译过程为 扫描程序-->语法分析-->语义分析-->源代码优化-->代码生成器-->目标代码优化

        扫描程序进行词法分析,从左向右,从上往下扫描源程序字符,识别出各个单词,确定单词类型。

        语法分析是根据语法规则,将输入的语句构建出分析树,或者语法树,也就是我们答案中提到的分析树parse tree或者语法树syntax tree。

        语义分析是根据上下文分析函数返回值类型是否对应这种语义检测,可以理解语法分析就是描述一个句子主宾谓是否符合规则,而语义用于检测句子的意思是否是正确的。

        目标代码生成指的是,把中间代码变换成为特定机器上的低级语言代码。

易错点3:

Makefile里主要包含了五个东西:显式规则、隐晦规则、变量定义、文件指示和注释

显式规则说明了,如何生成一个或多个目标文件。

        make有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写makefile,比如源文件与目标文件之间的时间关系判断之类。

        在makefile中可以定义变量,当makefile被执行时,其中的变量都会被扩展到相应的引用位置上,通常使用 $(var) 表示引用变量

        文件指示。包含在一个makefile中引用另一个makefile,类似C语言中的include。

        注释,makefile中可以使用 # 在行首表示行注释。

        默认的情况下,make命令会在当前目录下按顺序找寻文件名为“GNUmakefile”、“makefile”、“Makefile”的文件

伪对象.PHONY

        makefile中的伪对象表示对象名称并不代表真正的文件名,与实际存在的同名文件没有相互关系,因此伪对象不管同名目标文件是否存在都会执行对应的生成指令。

伪对象的作用有两个:

1. 使目标对象无论如何都要重新生成。

2. 并不生成目标文件,而是为了执行一些指令。

make会自动根据依赖对象检测目标对象是否需要重新生成.

        make在执行makefile规则中,根据语法规则,会分析目标对象与依赖对象的时间信息,判断是否在上一次生成后,源文件发生了修改,若发生了修改才需要重新生成。

二、编辑器vim

批量注释:首先从命令模式输入ctrl+v切换到V-BLOCK模式,使用hjkl进行选择,选择完后输入shitf+i=I进入插入模式,输入//,使用ESC切回V-BLOCK模式,可以看到选中行前面都加了//。

命令模式:快速编辑

快捷键:

定位

gg:快速回归光标

shift+g=G:快速把光标定位到结尾

n+shift+g = n+G:把光标定位到任意行

shift+$:定位到一行结尾

shift+^:定位到一行开头

n+hjkl:左下上右

w:以单词为单位向后移动

b:以单词为单位向前移动

编辑

n+yy:复制

n+p:粘贴

u:撤销历史操作(退出文件编辑无法进行撤销,但如果只是保存,没有退出还可以撤销)

ctrl+r:反撤销

n+dd:剪切当前行,或者删除

n+x:删除光标所在位置的字符

shift+x:光标右侧不动,左侧删除,也类似剪切。

r:替换光标所在字符,r->目标字符

nr:

shift+r=R:批量化替换

shift+~:大小写切换

底行模式

w/q/!,ZZ set nu/nonu

:!command 不退出vim情况下输入命令

:%s/dst/src/ 批量化替换

分屏操作

:vs new_src

ctrl+ww:切换光标位置

vim技巧

vim src+n 打开时定位到第n行。

三、Linux编译器---gcc/g++使用

gcc xxx.c -o xxx

1.预处理(宏替换,条件编译,去注释,头文件展开等)

gcc -E code.c -o code.i

-E表示进行程序翻译,在预处理完时停止

2.编译(生成汇编)

gcc -S code.i -o code.s

-S表示开始翻译,编译做完了,就停下来

3.汇编(生成机器可识别代码)

gcc -c code.s -o code.o

-c表示开始翻译,汇编完成就停下来。

code.o是可重定位目标文件,vs2022,xxx.obj

已经是二进制文件了,但不能直接运行。

4.链接(生成可执行文件或库文件)

gcc code.c -o code

库:

1.动态库:Linux(.so) Windows(.dll)

2.静态库:Linux(.a)  Windows(.lib)

理解预处理:

gcc code.c -o code -DM (命令行级的宏定义)

相当于#define M 100字符串插入到代码中。

预处理本质就是修改编辑我们的文本代码。

条件编译的用途:

1.社区版和专业版区分,使用条件编译进行代码动态裁剪。

2.内核源代码也是采用条件编译进行代码裁剪(例如嵌入式设备不需要联网就将网络部分裁剪)

3.多平台的开发工具、应用软件

为什么C/C++编译,要先变成汇编?

语言发展史:

开关

打孔编程(二进制编程)

汇编语言

C语言

C++/Java/Go/Python...

为什么要先变成汇编?

直接翻译成2进制,翻译代价太大了,C语言出来的时候,汇编语言已经发展得很成熟了,将C语言翻译成汇编(文本到文本),再由汇编翻译成2进制,翻译成本小。

编译器的自举过程:

第一个汇编语言编译器必须用2进制写,因为如果用汇编写没有对应汇编编译器编译汇编,产生了2进制的汇编语言编译器后,再用汇编语言写一个汇编编译器,用2进制的汇编编译器编译之后,就诞生了汇编语言写的汇编编译器,这个过程称为编译器的自举过程

因此,先有语言,然后才有该语言写的编译器。

什么叫做动态库,什么叫做动静态链接,如何理解?

库:

1.动态库:Linux(.so) Windows(.dll)

2.静态库:Linux(.a)  Windows(.lib)

库是一套方法或数据库,为我们开发提供最基本的保证(基本接口、功能,加速我们二次开发)。

libc.so    命名 lib+名称+.so*/.a*

libc.a

动态库:被多个程序共享,一旦缺失,会导致所以程序无法执行

静态库:只在链接时需要,运行时不需要。

动静态库对比:

1)动态库形成的可执行程序体积一定很小

2)可执行程序对静态库依赖小,动态库不能缺失

3)程序运行,需要加载到内存,静态链接的,会在内存中出现大量的重复代码

4)动态链接,比较节省内存和磁盘资源

ldd和file指令:

gcc code.c -o code-static -static(-static强制静态链接)

默认是动态链接

关于动态库:

重定向拷贝:cat srcfile > dstfile 

动态库本质:把语言层面公共的代码,在内存中未来只出现一份。

加载程序到内存时,相应的动态库也会被加载到内存中。

技术上理解库:

1.c->1.o

2.c->2.o

3.c->3.o

再链接o->exe。

库的本质是.o,但是为了防止丢失,打包成.so或.a。

本质上是被打包的.o文件。

链接本质,将.o进行合并。

四、自动化构建-make/Makefile(重点)

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

写成makefile/Makefile都可以。

实例:

code:code.c  (依赖关系)

        gcc -o code code.c  (依赖方法)

target: src1 src2 src3
    command

依赖关系中,target和src是一对多的关系

理解.PHONY以及不总被执行:

Access:最近访问时间,但由于查询是占文件操作的大部分,如果每一次查询都修改时间,那么就会导致每次都要修改访问时间,要进行一次IO操作,IO操作很消耗时间,要达到一定访问次数才更新时间,并非实时更新。

Modify:文件的内容变了,就要更新。

Change:文件属性变了,就更新。由于属性包括文件大小,时间。Modify了,即使文件大小不变,Modify时间变了,必然会影响文件属性,Change时间会更新。修改文件的权限也会更新Change时间。

文件=内容+属性

touch 已存在文件,更新三个时间

makefile的原理:

makefile技巧:

$()  //引用

加@  不打印makefile的内容

$@    最终目标

$^      最终目标依赖的众多文件列表

%.o:%.c 

把当前路径下的所有.o/.c依次展开,如果有100份,展成100份对应的依赖关系。

$< 将方法一个一个展开

1)SRC=${shell ls *.c}    获取当前目录下的所有.c文件

2)SRC=${wildcard *.c}

OBJ=${SRC:.c=.o}     SRC内部的文件名.c替换成同名.o

通用makefile:

#SRC=${shell ls *.c}                                                                                                             SRC=${wildcard *.c}
OBJ=${SRC:.c=.o} 
BIN=mycode

$(BIN):$(OBJ)
    @gcc -o $@ $^
    @echo "linking ... $^ to $@"
%.o:%.c
    @gcc -c $<
    @echo "compling ... $< to $@"
.PHONY:
clean:
    @rm -rf $(BIN) $(OBJ)
    @echo "delete $(BIN) $(OBJ)"
.PHONY:
PRINT:
    @echo ${SRC}
    @echo ${OBJ}

进度条:

\r回车,回归光标

\n换行,换到下一行。

\r\n回车换行。

缓冲区理解:一段内存块。

所以要让不加\n的printf立即显示,要加fflush(stdout);刷新一下缓冲区。

进度条实现,版本1:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define flag '#'

void progressBar1()
{
    char buff[101];
    memset(buff,0,101);
    static char s[] = "/-|\\";
    int cnt = 0;
    static int tmp = 0;
    while(cnt<=100)
    {
        tmp %= 4;
        printf("[%-100s][%d%%][%c]\r",buff,cnt,s[tmp]);
        fflush(stdout);
        usleep(10000);
        ++tmp;
        buff[cnt] = flag;
        ++cnt;
    }
    printf("\n");
}

版本2:

#include <stdio.h>
#include <string.h>
#define flag '#'

void progressBar2(double current,double total)
{
    char s[] = "/-|\\";
    char buff[101];
    memset(buff,0,101);
    int count = (int)((current/total)*100);
    for(int i = 0;i<count;++i)
    {
        buff[i] = flag;
    }
    static int k = 0;
    k%=4;
    printf("[%-100s][%d%%][%c]\r",buff,count,s[k++]);
    fflush(stdout);
}
#include <stdio.h>
#include<unistd.h>
#include "progressBar2.h"

double speed = 1.0;
double total = 1024.0;

void Upload()
{
    printf("Upload begin...\n");
    double current = 0;
    while(current<=total)
    {
        progressBar2(current,total);
        current+=speed;
        usleep(10000);
    }
    printf("\nCompleted total:%.1lf\n",total);
}

int main()
{
    Upload();
    return 0;
}

 五、版本控制器Git

1.如何理解版本控制?->Git && gitee || github(基于git的网站或平台)

版本控制:将每个文件版本进行记录,管理起来。

git是一个客户端,也是一个服务器,底层的版本控制器软件。

目的:

1.数据安全

2.协作开发

git clone 克隆到本地仓库

.git 隐藏的本地仓库,包含历史修改记录。

git数据提交的时候,只会提交变化的部分。

git add   //添加文件到git暂存区

git comimit -m "xxx"  //提交到本地git仓库,带上日志信息

git push    //推送到远程仓库

git log    //查看日志

git pull   //拉取远程仓库,达到同步

注意:

1.首次使用设置登录名和主机名

2.git版本管理,只管理源文件.c/.cpp/.h

3.-gitignore:需要忽略的特定后缀的文件列表。

4.远程仓库,相比较于任何人,都是最新的。

为什么要冲突?

提醒本地用户,需要和远程仓库进行同步了。

六、调试器-gdb/cgdb使用

gcc/g++默认release模式

加上-g选项,让最后形成的可执行程序,加上调试信息。---debug模式

查看debug信息:readelf -S BIN | grep -i debug

gdb bin(可执行程序)

quit退出

list 简写l显示源代码

b+行号:打断点

b+文件名:行号

b+函数名

d+断点编号:删除断点

info b:查看断点信息

r:运行程序,从头开始

gdb不退出:断点编号依次递增。

next/n:逐过程

step/s:逐语句

bt:查看栈帧信息

finish:结束当前函数

p xxx:查看变量的值(表达式)

objdump -S mycode > mycode.s(反汇编)

断点可以被使能:

disable + 断点编号 禁用断点

enable + 断点编号 使用断点

调试的本质:

1.找到问题

2.查看代码上下文

断点的本质,把代码进行块级别的划分。

c:运行到下一个断点处

until+行号:将程序运行到指定行号(局部范围快速执行)

类似VS监视窗口:

display+变量 长期显示变量值

undisplay+显示编号 删除对应编号的长显示

注:变量生命周期结束,自动删除对应变量的长显示

info locals 查看当前函数的临时变量

调试技巧:

watch + 变量名 监视变量的变化,变化了就会打印提示信息(也是点信息,c也会跳转至对应改变这个变量的位置)

set vat + 变量名 = xxx 暂时更改变量名对应的值

条件断点:

b + 行号 if expression (常用于循环内部)

给已存在的断点设置条件:

condition + 断点编号 expression

ESC:进入代码屏,滚动代码

i:回到gdb屏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

挺6的还

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值