当前位置: 首页 > article >正文

Linux中的基本开发工具(上)

目录

软件包管理器

软件生态

yum操作

修改配置yum源

编译器vim

vim的基本概念

命令模式

低行模式

批量化操作

扩展命令

vim 配置

vim的配置文件

普通用户配置

g++/gcc的使用

预处理

编译(生成汇编)

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

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

理解代码报错

预处理阶段错误

编译阶段错误(核心阶段)

链接阶段错误

静态库和动态库(共享库)

静态链接和动态链接

理解过程

再次理解


软件包管理器

我们在linux上下载安装软件,通常有三种情况:

  1. 下载软件的源代码,到本地自行编译运行
  2. 软件包安装---rpm命令
  3. 包管理器yum(centos)  apt/apt-get(ubuntu)

我们推荐第三种,为什么?

第一种:

下载软件的源代码,自己到本地去运行,难免会出现一些各种各样的问题,比如系统兼容性问题,而且甚至会出现这种问题:为什么在这台机器运行,在我这台机器运行不了?问题情况百出!而且用户也比较麻烦。

第二种:

有些人把软件代码提前编译好做成一个软件包(可以理解成Windows上的安装程序),我们只需要下载这个软件包即可,但是依然有问题,比如我下载安装A软件包,而单单下载一个软件包是不行的,有可能这个软件依赖多个库文件,甚至它依赖其他软件中的库文件,这也叫依赖缺失

库文件是不断更新的,而有些新软件用兼容不了老的库,叫做版本兼容性问题!

我们在搭建环境时,其实就是解决这两种问题

第三种:

我们使用包管理器安装,先是网络下载,再是安装,其实安装就是拷贝,将软件拷贝到系统目录里面,而我们知道普通用户是无法在系统目录里进行写操作的!如图:

我们看到,大部分只有写和可执行权限,没有写权限,所以我们下载安装软件需要root权限,也就是这个原因,软件安装到系统里面,只需要安装一次,任何人都能使用!

而且使用包管理器安装软件,它会自动解决包依赖问题!

软件包和软件包管理器,就好⽐"App"和"应⽤商店"这样的关系。

软件生态

我们如何评判一款操作系统的好坏?

我们可以看它的内核版本,社区,文档,它所暴露出来的问题,它针对的用户,和它背后所配套的一系列软件等等......

我们主要看的就是它的生态!

那为什么linux操作系统要在社区提供免费的软件?免费的供我们下载使用呢?

这个社区后面有很多程序员去维护它,他们把自己开发的软件编译好打包成软件包,然后上传到社区所维护的软件包管理器(一台云服务器),我们如果需要下载的话,只需要利用yum/apt软件直接下载安装即可!

而yum/apt软件只不过是在做这样的工作:访问软件包管理器,查找我们需要的软件包,下载,返回下载!

那yum/apt软件是如何知道这台软件包管理器的地址链接呢?

通常我们的操作系统内部是有内置链接的,我们只需要告诉yum/apt要下载安装哪款软件即可!

我们知道,linux操作系统是外国人搞出来的,社区也肯定在外国,那么怎么让国内大部分人也使用到linux配套的一系列软件呢?

这时候就有了镜像的概念,我们可以把国外的那台软件包管理器直接镜像到国内,那么国内需要下载安装的话,只需要修改一下我们操作系统内部的内置链接不就行了!

图:

国内有很多Linux软件安装镜像源,比如清华大学镜像源,阿里镜像源等等!

yum操作

我们前面说过,yum它就相当于是一个“应用商店”,我们当然可以将我们需要的软件在这个“应用商店”搜一遍。

注意:yum操作必须联网,判断联网如下。

查找:

下载:

卸载:

修改配置yum源

Centos  yum源配置文件在 /etc/yum.repos.d/ 路径下:可以看到

ubuntu下:

修改配置步骤:

1.备份本地的标准源文件:

2.下载对应镜像的.repo文件,然后上传到linux服务器中,也可以直接命令下载:

注意:下载到/etc/yum.repos.d/ 目录中,名字必须和先前备份的文件原先的名字一致!

以华为镜像源为例:

3.清除缓存

命令:

yum clean all

4.生成新的缓存

命令:

yum makecache

完成!!!

现在就可以下载了!!!

打开CentOS-Base.repo文件我们可以看到:

编译器vim

vi/vim的区别简单点来说,它们都是多模式编辑器,不同的是vim是vi的升级版本,它不仅兼容vi的所 有指令,⽽且还有⼀些新的特性在⾥⾯。例如语法加亮,可视化操作不仅可以在终端运⾏,也可以运 ⾏于xwindow、macos、windows。

vim的基本概念

vim是多模式编辑器,它有很多种模式,我们主要学习掌握三种即可:命令模式,插入模式,低行模式。

三种模式功能:

  • 正常/普通/命令模式(Normalmode):控制屏幕光标的移动,字符、字或⾏的删除,移动复制某区段及进⼊Insertmode下,或者到last line mode
  • 插⼊模式(Insertmode):只有在Insertmode下,才可以做⽂字输⼊,按「ESC」键可回到命令⾏模式。该模式是我们后⾯⽤ 的最频繁的编辑模式。
  • 末⾏模式(lastlinemode):⽂件保存或退出,也可以进⾏⽂件替换,找字符串,列出⾏号等操作。

命令模式

命令模式主要达到的功能是快速编辑!

  1. gg : 光标回到首行最左边
  2. G:光标回到最后一行最左边
  3. nG:光标到某一行的最左边 (n是数字)
  4. $:光标到当前行的最右边
  5. ^:光标到当前行的最左边

光标移动:

h:向左     L:向右

k:向上      j:向左

当然前面可以加上数字移动:一下移动n个光标!

当然利用向上左右键也可以移动,但是也可以h l k j四个键移动。

因为以前的键盘没有向上左右键:

我们继续介绍:下列都能在前面加上数字进行多行操作

  1. w:以单词为单位向后移动
  2. b:以单词为单位向前移动
  3. yy:复制当前行
  4. p:在光标位置粘贴
  5. dd:剪切-->删掉且复制当前行
  6. x:删掉当前位置字符(左侧不动,右侧删除)
  7. X:删掉当前字符(右侧不动,左侧删除相当于回车)
  8. ~:字符大小写切换

继续介绍:

r:替换当前字符。(能在前面加数字)

R:进入替换模式,可以进行批量化替换!

在替换模式中,甚至可以插入新内容,不止于替换功能!

#:选中单词,再按下n按钮可以逆向查找。

u:撤销操作

ctrl+r:撤销u操作

低行模式

wq!:w表示保存,q表示退出,!表示强制。

ZZ:这个指令不需要低行模式,在命令模式中就可以使用,保存退出的功能。

set nonu/nu:(不)显示行数。

在低行模式中,也可以在不退出vim的前提下敲命令:

!ls -l:不退出vim,显示当前文件。

!gcc xxx.c:不退出vim,编译可执行程序。

%s /dst/src:批量化替换,将dst替换成src

/dst:查找dst,按n光标移动到下一个。

批量化操作

在命令模式中按ctrl+v即可进入视图模式,进行批量化操作。

插入:

ctrl+v进入视图模式,利用h j k l 四个键光标选中需要操作的字符,按下shift+i 进入插入模式,进行插入操作,按下Esc键即可显现批量插入的内容。

删除:

ctrl+v进入视图模式,利用h j k l 四个键光标选中需要操作的字符,直接按下 d 键即可删除需要批量化操作的内容。

注意:在命令模式下的快捷键也同样适用。

扩展命令

1.在命令行中,编译器打开某一个源文件,我们可以直接在后面加数字:

vim  dst.c  n:光标跳转到dst.c文件的第n行。

2.在命令行中,我们可以这样快速调用最近的指令:

!v:自动调用最近v开头的指令。

!l:自动调用最近l开头的指令。

我们在敲代码的时候,有时候可能需要多个源文件共同写代码:

在低行模式中,敲上:vs  dst.c  分屏操作,dst.c自动被创建

ctrl+w+w:在多个文件分屏情况下,光标跳转到另一个文件中。

模式转换图:

vim 配置

在根目录下:

usr目录下一般存放着用户安装的软件和资源。

etc一般存放着系统的配置文件。

bin目录下存放着系统的可执行文件,存放着基础指令。

var目录(全称 "variable",意为“可变的”)用于存放经常变化的数据,例如日志、缓存、临时文件、数据库(/var/lib/mysql)等。

lib目录(通常指 /lib 和 /usr/lib)是存放共享库文件的核心位置。库文件(.so动态库和.a静态库)。

dev目录存放着设备文件,比如:系统中的硬件设备(如硬盘、键盘)或虚拟设备(如随机设备)。

tmp目录是临时文件的存放位置。

sys目录是一个虚拟文件系统,主要用于动态展示和管理硬件设备、驱动及内核对象

而vim 是一个编译器,它是个软件同时也是一个可执行文件(指令)。

vim的配置文件

vim的配置文件在系统层面是在/etc/vimrc文件中

我们只需要在这个文件中配置相关信息,vim就能立即生效!

普通用户配置

在系统层面的配置文件,只要配置好了,所以用户都能使用,但是其他用户不想使用这个配置好的vim,想要自己配置适合自己的vim,怎么办?

在系统层面有一个配置文件可供所有用户使用,我们可以在普通用户的家目录里面配置一个.vimrc文件,将你将配置的功能配置到这个文件中去,那么这个用户在使用vim的时候使用的是自己家目录下的配置文件,也就是说会优先调用家目录下的配置文件!

配置:

写配置功能:

可自行添加!

当然如果想要更多功能,我们需要安装一些插件,这里不过多阐述!

g++/gcc的使用

gcc是编译 .C 文件的,而g++是编译 .cpp 文件的,gcc用到的指令,g++同样适用,我们这里以gcc为演示。

预处理

进行宏替换,去注释,头文件展开等。也就是这个作用,其实形成的.i文件里面的内容其实依然是我们的计算机语言(如c/c++代码)。

预处理将 .c 文件翻译成 .i 文件。

语法: gcc -E  src.c  -o  src.i

例子:

为什么源文件就几行,.i文件几百行?

条件编译的用途:

  1. 软件进行专业度,收费情况的区分,还可以代码动态裁剪
  2. 内核源代码也是条件编译来进行裁剪的
  3. 开发工具,应用软件

编译(生成汇编)

编译形成.s文件,也就是生成汇编。

在这个阶段中,gcc⾸先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的⼯作, 在检查⽆误后,gcc把代码翻译成汇编语⾔。

语法:gcc  -S src.i  -o  src.s

例子:

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

生成 .o 文件(二进制文件),汇编语言,它就是将编译形成的文件(.s文件)汇编成.o文件。

在windows中二进制是.obj文件,这点和linux不同。

语法:gcc  -c  src.s  -o src.o 

例子:

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

将多个文件链接在一起。

例子:

链接阶段的核心任务是合并编译产物,但根据目标不同会产生两类文件:可执行文件和库文件

而我们编译产生的是二进制文件(.o文件),链接时合并编译产物,其实链接后的文件(可执行文件和库文件)也是二进制文件。(计算机只认识二进制文件)。

如果有多个源文件:

理解代码报错

预处理阶段错误

  • 典型错误:头文件找不到、宏定义语法错误、条件编译逻辑错误

编译阶段错误(核心阶段)

  • 典型错误:语法错误、类型不匹配、未声明变量/函数、作用域错误

汇编阶段错误

  • 罕见情况:内联汇编语法错误、硬件架构不兼容指令

链接阶段错误

  • 典型错误:未定义的函数/变量、重复的符号定义、库文件缺失

静态库和动态库(共享库)

静态库:

  • 静态库是指编译链接时,把库⽂件的代码全部加⼊到可执⾏⽂件中,因此⽣成的⽂件⽐较⼤,但在运 ⾏时也就不再需要库⽂件了。其后缀名⼀般为“.a”
  • 动态库与之相反,在编译链接时并没有把库⽂件的代码加⼊到可执⾏⽂件中,⽽是在程序执⾏时由 运⾏时链接⽂件加载库,这样可以节省系统的开销。动态库⼀般后缀名为“.so”,如前⾯所述的 libc.so.6 就是动态库。gcc在编译时默认使⽤动态库。完成了链接之后,gcc就可以⽣成可执⾏⽂件。

查看库信息:

查询可执行文件依赖哪些动态库:

头文件存放地方:

库存放地方:

静态链接和动态链接

在我们的实际开发中,不可能将所有代码放在⼀个源⽂件中,所以会出现多个源⽂件,⽽且多个源⽂ 件之间不是独⽴的,⽽会存在多种依赖关系,如⼀个源⽂件可能要调⽤另⼀个源⽂件中定义的函数, 但是每个源⽂件都是独⽴编译的,即每个*.c⽂件会形成⼀个*.o⽂件,为了满⾜前⾯说的依赖关系,则 需要将这些源⽂件产⽣的⽬标⽂件进⾏链接,从⽽形成⼀个可以执⾏的程序。这个链接的过程就是静 态链接。静态链接的缺点很明显:

  • 浪费空间:因为每个可执⾏程序中对所有需要的⽬标⽂件都要有⼀份副本,所以如果多个程序对 同⼀个⽬标⽂件都有依赖,如多个程序中都调⽤了printf()函数,则这多个程序中都含有 printf.o,所以同⼀个⽬标⽂件都在内存存在多个副本;
  • 更新⽐较困难:因为每当库函数的代码修改了,这个时候就需要重新进⾏编译链接形成可执⾏程 序。但是静态链接的优点就是,在可执⾏程序中已经具备了所有执⾏程序所需要的任何东西,在 执⾏的时候运⾏速度快。

动态链接的出现解决了静态链接中提到问题。动态链接的基本思想是把程序按照模块拆分成各个相对 独⽴部分,在程序运⾏时才将它们链接在⼀起形成⼀个完整的程序,⽽不是像静态链接⼀样把所有程序模块都链接成⼀个单独的可执⾏⽂件。

静态链接生成:

理解过程

由此可以看出:(重点)

  • 如果有多个程序,动态库一旦缺失,导致所有程序都无法运行。
  • 静态库只有在链接的时候有用,一旦形成可执行程序,静态库可以不在需要。
  • 动态库形成的可执行程序提交一定很小。
  • 可执行程序对静态库依赖度小,而动态库不能缺失。
  • 程序运行,需要加载到内存,静态链接的,会在内存中出现大量重复代码。
  • 动态链接,比较节省内存和磁盘资源。

再次理解

我们编写好了程序,进行预处理(宏替换,去注释),编译(检查语法错误),汇编(生成机器可识别代码也就是二进制文件),最后进行动静态链接(大部分都是动态链接)生成可执行文件。

动态库只会在内存里面加载一遍,哪怕有很多个源文件,而静态库会在内存里面加载很多次(在有很多源文件的条件下)。

为什么会有库?

开发者将常用的方法,提前写好,进行预处理,编译,汇编成 .o 文件,然后将这些.o文件打包成库文件(.so或.a文件),然后供我们链接使用它们,而我们代码中的头文件包含,其实就是方法的声明,告诉编译器有这个函数。也就是这个头文件包含,后续的编译才没报错。

所有在开发一个项目时,我们常常将方法,声明和定义分离(新建一个头文件(放方法声明)和源文件(放方法实现)),我们只需要包含头文件(我们建立的头文件),最后链接在一起,如果新建源文件中没有实现函数,那么编译就会报错,文件链接不起来。

所以头文件就是声明的集合(不止于函数声明),库文件其实就是.o文件的集合

好了,我们下期见!


http://www.kler.cn/a/600797.html

相关文章:

  • 基于Spring Boot的党员学习交流平台的设计与实现(LW+源码+讲解)
  • 【微服务架构】SpringCloud(七):配置中心 Spring Cloud Config
  • OpenCV图像拼接(7)根据权重图对源图像进行归一化处理函数normalizeUsingWeightMap()
  • 洛谷 P1351 [NOIP 2014 提高组] 联合权值(树)
  • HTML5 canvas圆形泡泡动画背景特效
  • 最长连续子序列和的所含元素 -- Kadane算法拓展
  • R语言——字符串
  • 一文解读DeepSeek的安全风险、挑战与应对策略
  • C#基础学习(一)复杂数据类型之枚举
  • 【Linux】从开发到系统管理深入理解环境变量
  • RocketMQ 详细知识点总结
  • 文章记单词 | 第2篇(六级)
  • STM32/GD32主要学习内容
  • K8s的网络
  • Java高频面试之集合-18
  • 目录遍历漏洞复现
  • 从零构建大语言模型全栈开发指南:第二部分:模型架构设计与实现-2.2.2文本生成逻辑:Top-k采样与温度控制
  • Vibe Coding:编程的未来?
  • Rust Web 开发新选择:探索 Hyperlane 轻量级 HTTP 服务器框架
  • 《TypeScript 面试八股:高频考点与核心知识点详解》