我们在安装一个软件之前,需要先下载对应的软件包,但是这个软件包并不存在于我们本地的计算机磁盘,而是存在于远端服务器上;那么计算机如何知道该软件存在于具体的哪一台服务器上呢?
对于电脑来说,我们一般通过搜索对应软件的官网来得到相应软件包;对于手机来说,表面上我们通过手机自带的应用商店来下载软件包,但实际上应用商店里面并不存在软件包,而只是存在着对应软件官网的链接,最后我们的软件包还是从官网上下载的;
其次,这些软件包是由谁提供的呢?答案很明显,它们是由一些企业、组织或个人提供的;这些企业、组织以及个人为了某种利益编写出了软件包,然后将其放在了对应的服务器上。
yum (Yellow dog Updater, Modified) 是Linux下非常常用的一种包管理器;主要应用在 Fedora, RedHat,Centos 等发行版上;软件包和软件包管理器, 就好比 “App” 和 “应用商店” 这样的关系。
在Linux下安装软件的方法大概有以下三种:
1)下载到程序的源代码,自行进行编译,得到可执行程序。
2)获取rpm安装包,通过rpm命令进行安装。(未解决软件的依赖关系)
3)通过yum进行安装软件。(常用)
注意:一个服务器同一时刻只允许一个yum进行安装,不能在同一时刻同时安装多个软件。
我国的一些高校以及公司就 镜像了国外的软件服务,即把国外服务器上的软件拷贝到了国内自己公司的服务器上,使得我们可以直接访问国内的服务器来下载软件;
但是只拷贝软件还不行,因为 yum 中下载软件时默认访问的链接还是国外的,所以这些高校/公司还提供了一套国内的下载链接配置文件 – yum 源配置文件;
在Linux中,yum 源配置文件是存在于 /etc/yum.repos.d/ 目录下的 CentOS-Base.repo 文件:
ll /etc/yum.repos.d/
如果你使用的是云服务器,那么 yum 源一般都是配置好的,虚拟机的配置方法会更麻烦一点,而且还需要利用ping值检查网络是否处于连接状态
yum list
但是这样出来的东西很多很杂
我们可以通过 yum list 命令罗列出当前一共有哪些软件包;但由于包的数目非常之多, 所以我们一般使用 grep 命令来筛选出我们关注的包;如:
grep指令http://t.csdn.cn/g1aDI
yum list| grep 要搜索的内容
注意事项:
- 软件包名称构成:主版本号.次版本号.源程序发行号-软件包的发行号.主机平台.cpu架构;
- “x86_64” 后缀表示64位系统的安装包,“i686” 后缀表示32位系统安装包,选择包时要和系统匹配;
- “el7” 表示操作系统发行版的版本: “el7” 表示的是 centos7/redhat7,“el6” 表示 centos6/redhat6;
- 最后一列中 base 表示的是 “软件源” 的名称, 类似于 “小米应用商店”, “华为应用商店” 这样的概念;
rz:上传文件(其实Windows直接拖到xshell中也是可以的)
sz:将xshell文件给到Linux 这个没有办法拖 因为Linux下的文件不像windows一样,是可以找到实体的
指令: sudo yum install(可以加-y) 软件名
(其中 -y 代表不询问直接安装)(sudo是因为只有root才可以装)
安装完毕
sl命令不同于ls命令,sl命令是以动画形式呈现小火车的趣味性命令,虽无实用价值,但亦可陶冶情操,愉悦心情。
有一些软件并没有被纳入 Centos、Ubuntu、Kail等相关生态平台的官方软件集合中,如果我们想使用这些软件,需要安装 非官方软件集合列表 – epel-realse
注意事项:
- 安装软件时由于需要向系统目录中写入内容,一般需要 sudo 或者切到 root 账户下才能完成;
- yum安装软件只能一个装完了再装另一个;正在yum安装一个软件的过程中,如果再尝试用yum安装另外一个软件,yum会报错;
- 软件和软件之间是有关联的,即具有一定的耦合度; yum 为了解决软件之间相互依赖的问题,有时候在安装一个软件会连带安装其他一些软件。
指令: sudo yum remove -y 软件名
注意:关于 yum 的所有操作必须保证主机 (虚拟机) 网络畅通;可以通过 ping 指令验证网络
ping + 网站名字 就可以查看现在网络是否健康
由于我将我的Linux配置成了 ctrl+c 是复制 ,那么也就是说
ctrl+shift+c 就是强制退出执行程序的代码
为什么别用root配置 请看第5点
vim 是一个编辑器 和windows下的记事本没有任何区别
这个编辑器有一个好处 是一个功能强大 多模式的编辑器
vim 一共有12种模式,我们目前掌握其中三种模式即可,分别是命令模式(command mode)、插入模式(Insert mode)和底行模式(last line mode),各模式的功能区分如下:
存在的意义:通过各种各样的命令,来简化操作,加快使用效率
控制屏幕光标的移动,字符、字或行的删除;
移动复制某区段以及进入Insert mode下,或者到 last line mode;
只有在Insert mode下,才可以做文字输入;
按「ESC」键可回到命令行模式,该模式是我们后面用的最频繁的编辑模式;
文件保存或退出,也可以进行文件替换,找字符串,列出行号等操作;
在命令模式下,输入 : 即可进入该模式;
我们可以在底行模式下输入 “ :help vim-modes” 来查看 vim 的所有模式。
我们使用 vim 打开一个文件时默认处于命令模式,然后我们可以通过如下指令切换到其他模式:
vim test.c (后面写的是 touch的文件名字)
打开是黑黑的这个 这个就是命令模式
【命令模式】切换至【插入模式】
- 输入「i」:在当前光标处进入插入模式(我一般用i insert 多好记 但是也别忘了别的)
- 输入「a」:在当前光标的后一位置进入插入模式
- 输入「o」:在当前光标处新起一行进入插入模式
按完之后,左下角就是insert了
【命令模式】切换至【底行模式】
- 输入「Shift+;」即可,实际上就是输入「:」
左下角变成这样,那么就是底行模式
【插入模式】或【底行模式】切换至【命令模式】
- 插入模式或是底行模式切换至命令模式都是直接按一下「Esc」键即可
小羊注:vim 下的所有删除操作都相当于 Windows 下的剪切操作
小羊注:在使用底行模式之前,记住先按「Esc」键确定你已经处于命令模式,再按「:」即可进入底行模式
将来提权sudo的时候 会用到!
在目录 /etc/ 下面,我们可以找到有一个名为 vimrc 的文件,这是系统中公共的vim配置文件,对所有用户都有效
所以我们要对 vim 进行一些其他的基本配置,使得我们能够在便捷的在vim中编写C/C++程序;特别注意:
虽然Linux中的所有用户使用的都是同一个vim程序,但是大家使用的是不同的vim配置,因为每个用户的家目录下都会有一个属于自己的 .vimrc 文件,这个文件中保存的就是专属于这个用户的 vim 配置。所以我在vim的基本使用上面写别用root,以免将来配置出现问题。
一些简单的vim配置:
先用vim进入.vimrc
之后检查发现已经全部写好
但是有没有一键配置的方法?? 答案是有的
curl -sLf https://gitee.com/HGtz2222/VimForCpp/raw/master/install.sh -o ./install.sh && bash ./install.sh
大家复制这个到xshell 并且执行 下面我和大家一起配置:
接着我们输入root密码:
然后我们输入 “source ~/.bashrc” 或者重启终端即可使 vim 配置失效:
可以看到,配置完成后的 vim 不仅会显示当前模式、文件名、字符个数,还支持自动缩进、自动补齐 (语法、括号、引号等等)
但是这里存在一个小问题:此处的自动缩进默认是两个字符,而我们编写C/C++程序时一般都要求缩进四个字符,所以我们需要打开 .vimrc 文件对默认缩进进行修改:
至此,我们的 vim 一键配置就完成了!!!!! 欢呼!!!
我们往往用su 或者 su- 来让我们变成root执行yum等等只有root才可以执行的命令
但是我们在提权的时候,我们的身份通过whoami查询后变成了root
sudo就是一个可以不改变身份但拥有root权力的短暂提权指令,但是往往都需要配置,这是不配置的情况:
那么这个时候就需要用vim打开文件进行配置了
vim(空格)/etc/sudoers
注意vim后面要加空格
在这波操作中注意事项:
1. xiao_yang并不在受信任的用户里面,所以得添加
2.因为是只读文件,这个时候感叹号就派上用场了,我先保存,之后再强制退出
现在,我们就可以在普通用户下使用 sudo 对指令进行提权了:
这个时候在配置完之后很容易发现,就成功可以提权啦!!
gcc和g++分别是GNU的C和C++的编译器,gcc和g++在执行编译的时候一般有以下四个步骤:
1)预处理(头文件展开、去注释、宏替换、条件编译)。
2)编译(C代码翻译成汇编语言)。
3)汇编(汇编代码转为二进制目标代码)。
4)链接(将汇编过程产生的二进制代码进行链接)。
语法: gcc/g++ 选项 文件
常用选项:
-E 只进行预处理,这个不生成文件,你需要把他重定向到一个输出文件里面(否则将把预处理后的结果打印到屏幕上,我们gcc -E 又加-o 就是因为全部写在屏幕上杂乱无章)
-S 编译到汇编语言,不进行汇编和链接,即只进行预处理和编译。(照样不生成文件,也是打印在屏幕上的)
-c 编译到目标代码
-o 将处理结果输出到指定文件,该选项后需紧跟输出文件名。(也就是有生成文件的能力)
-static 此选项对生成的文件采用静态链接。
-g 生成调试信息(若不携带该选项则默认生成release版本)。
-shared 此选项将尽量使用动态库,生成文件较小。
-w 不生成任何警告信息。
Wall 生成所有警告信息。
-O0/-O1/-O2/-O3 编译器优化选项的四个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高。
gcc/g++ 的安装:(大概率是都已经安装好了 latest)
sudo yum install -y gcc
yum install -y gcc-c++ libstdc++-devel
gcc -E test.c -o test.i
现在,我们在底行模式中 vs test.c 就可以同时看到俩个文件
gcc -s test.i -o test.s
gcc -c test.s -o test.o
gcc test.o -o test
注意: 链接后生成的也是二进制文件。
我们在编写代码的时候,除了自己实现函数之外,我们还会去调用函数库中的代码,比如 scanf/printf/malloc/fopen;但是我们要明白,库中的代码是别人给我们写好供我们直接使用的,即我们只有该函数的调用,而没有函数的实现;
同时,程序在预处理、编译和汇编阶段处理的都是我们自己编写的代码,只有在链接的时候,库函数的实现才会和我们的代码关联起来 (符号表的重定位);所以,链接的本质是我们在调用库函数时如何与标准库相关联的问题
程序一共有两种链接方式:动态链接与静态链接
动态链接:是指执行代码时,如果遇到库函数调用就跳转到动态库中对应函数的定义处,然后执行该函数,执行完毕后再跳转回原程序并继续往下执行
优点:是形成的可执行程序小
缺点:是受到动态库变动 (删除、升级等) 的影响。
静态链接:直接将本程序内部要使用的库函数从对应的静态库中拷贝一份过来
优点:不与静态库产生关联,即不受静态库变动 (删除、升级等) 的影响
缺点:形成的可执行程序非常大
函数库是一些事先写好的,用于给别人复用的函数的集合,函数库一般分为静态库和动态库两种:
静态库是指编译链接时,把需要的库文件代码全部拷贝到可执行文件中,因此生成的文件非常大,但在运行时也就不再需要库文件了
在Linux下其后缀名为 “.a”,在Windows下其后缀名为 “.lib”;
动态库也被称为共享库,它与静态库相反,在编译链接时并没有把相应的库文件代码加入到可执行文件中,而是在程序执行时由运行时链接文件来加载库,这样可以节省系统的开销,在Linux下其后缀名为 “.so”,在Windows下其后缀名为 “.dll”;
注:动态链接必须使用动态库,静态链接必须使用静态库;即进行动态链接时只能跳转到动态库中对应函数的实现处,进行静态链接时只能拷贝静态库中的函数。
Linux中默认使用动态库进行动态链接:gcc默认生成的二进制程序,是动态链接的,这点可以通过 file 指令来验证
原因如下:
Linux 一般都会自动安装C语言动态库,因为Linux下的大多数指令以及我们默认使用 gcc 编译得到的可执行程序都是进行动态链接,依赖C动态库的
但是C静态库、C++静态库可能就需要我们自己安装了
sudo yum install -y glibc-static
sudo yum install -y libstdc++-static
虽然gcc和g++默认采用的是动态链接,但如果我们需要使用静态链接,带上-static选项即可
gcc test.c -o test.s -static
可以看到,以静态链接方式形成的可执行程序比动态链接形成的要大100~200倍,即一个动态链接只有100M的文件,静态链接就会变成十几个G,二者之间相差非常大
1、debug版本:程序本身会被加入更多的调试信息,以便于进行调试。
2、release版本:不会添加任何调试信息,是不可调试的。
在Linux当中gcc/g++默认生成的可执行程序是release版本的,是不可被调试的。如果想生成debug版本,就需要在使用gcc/g++生成可执行程序时加上-g选项
对同一份源代码分别生成其release版本和debug版本的可执行程序,并通过ll指令可以看到,debug版本发布的可执行程序的大小比release版本发布的可执行程序的大小要大一点,其原因就是以debug版本发布的可执行程序当中包含了更多的调试信息
指令: gdb 文件名
添加断点 和 删除断点是不一样的操作,添加直接行号 但是删除的时候 断点拥有自己的序号了已经 从0123开始
编写 makefile,最重要的是编写 依赖关系和依赖方法
当我们和老爸要钱的时候:依赖关系:我是你儿子;方法:打电话
依赖关系:指一个文件依赖另外一个文件,即想要得到一个文件,目录下必须先有另外一个文件
例如,test.o文件是由test.c文件通过预处理、编译以及汇编之后生成的文件,所以test.c文件的改变会影响test.o,所以说test.o文件依赖于test.c文件
依赖方法:则是指如何根据依赖文件来得到目标文件
例如,test.o依赖于test.c,而test.c通过gcc -c test.c -o
test.o指令就可以得到test.o,那么test.o依赖于test.c的依赖方法就是gcc -c test.c -o test.o
编写mkfile的时候,也有一些需要注意的地方,小羊注:
- makefile 的文件名必须是 makefile/Makefile,不能是其他名称,否则 make 识别不了;
- 依赖文件可以有多个,也可以没有;
- 依赖方法必须以 [Tab] 键开头,特别注意不能是四个空格;
步骤一: 在源文件所在目录下创建一个名为Makefile/makefile的文件
步骤二:编写Makefile文件 (vim Makefile)
Makefile文件最简单的编写格式是,先写出文件的依赖关系,然后写出这些文件之间的依赖方法,依次写下去
如上:mytest依赖 test.c,依赖方法是 gcc 编译,clean 不依赖任何文件,依赖方法是 rm -f 指令;其中 .PHONY 修饰 clean 表示其是一个伪目标,总是被执行 (具体细节下文解释)
编写完毕Makefile文件后保存退出:wq,然后在命令行当中执行make指令便可以生成可执行程序,以及该过程产生的中间产物
单纯对例子的粗略解释:
mytest: test.c
gcc test.c -o mytest
这个规则告诉 Make 工具如何构建目标 `mytest`。它表示 `mytest` 依赖于 `test.c` 这个文件。如果 `test.c` 文件的修改时间比 `mytest` 更新(或者 `mytest` 不存在),那么 Make 会执行接下来的命令来构建 `mytest`。
.PHONY: clean
clean:
rm -f mytest
这个规则定义了一个伪目标 `.PHONY` 和一个目标 `clean`。`.PHONY` 用于声明 `clean` 是一个伪目标,即不是真正的文件。`clean` 目标用于清理构建生成的中间文件和目标文件,以及最终生成的可执行文件 `mytest`。执行 `make clean` 命令时,Make 会执行 `clean` 目标的命令,即删除名为 `mytest` 的文件。单纯写make的时候不会执行clean
工作流程:
1. 当你执行 `make` 命令时,Make 工具会寻找当前目录下的 `Makefile` 文件。
2. Make 读取 `Makefile` 中的规则,并检查目标 `mytest` 是否需要重新构建。它发现目标 `mytest` 依赖于 `test.c`,并且 `test.c` 存在或者其修改时间较 `mytest` 更新,所以 `mytest` 需要重新构建。
3. Make 执行 `gcc test.c -o mytest` 命令来编译 `test.c` 并生成可执行文件 `mytest`。
4. 如果你执行 `make clean` 命令,Make 工具会执行 `clean` 目标的命令,即删除 `mytest` 文件。
`Makefile` 文件的目的是让构建过程自动化和简化。通过定义适当的规则和依赖关系,Make 工具可以只编译需要更新的文件,从而加快构建过程,并确保项目的正确性和一致性。
在Linux下,我们输入 make 命令后,make 会在当前目录下找寻名为 “Makefile” 或 “makefile” 的文件;如果找到,它会把文件中的第一个目标文件作为最终的目标文件;如果找不到,就打印提示信息;在上面的C语言例子中,makefile 中一共有两个目标文件
没有生成clean,虽然clean也是目标文件:
这样就可以执行俩段代码:
修改一下makefile文件:
test.out:test.o
gcc test.o -o test.out
test.o:test.s
gcc -c test.c -o test.o
test.s:test.i
gcc -S test.i -o test.s
test.i:test.c
gcc -E test.c -o test.i
.PHONY:clean
clean:
rm -f test.i test.s test.o test.out
我们知道,我们输入 make 命令后,make 会在当前目录下找寻名为 “Makefile” 或 “makefile” 的文件;如果找到,它会把文件中的第一个目标文件作为最终的目标文件 (上面例子中的 test.out),但是如果 test.out 所依赖的 test.o 文件不存在,那么 make 会在当前文件中找目标为 test.o 文件的依赖性,再根据该一个规则来生成 test.o 文件 (类似于数据结构栈 – 后进先出);
如果 test.o 的依赖文件也不存在,则继续执行该规则,直到找到存在依赖文件的目标文件,得到目标文件后层层返回形成路径上的其他目标文件;或者最后被依赖的文件找不到,直接退出并报错;
这就是整个 make 的依赖性,make 会一层又一层地去找文件的依赖关系,直到最终编译出最开始我们需要的目标文件。
在上面的例子中,test.out 依赖的 test.o 不存在,make 会去寻找以 test.o 为目标文件的依赖关系;test.o 依赖的 test.s 也不存在,make 又会去找 以 test.s 为目标文件的依赖关系;然后 test.s 依赖 test.i,最后,test.i 的依赖文件 test.c 终于存在了,make 就会根据 test.i 的依赖方法形成 test.i,再逐步形成 test.s、test.o,直到最后形成 test.out。
在 makefile 中,我们常用 clean 来作为项目清理的目标文件,同时,由于项目清理不需要依赖其他文件,所以 clean 也不存在依赖关系
clean 没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,所以我们需要显示指定 : make clean
最后,像 clean 这种目标文件,我们一般都会用 .PHONY 将其设置为伪目标,
伪目标的特性是:
该目标文件总是被执行
当我们对同一个源文件多次 make,我们会发现第一次程序正常编译,但第二次及以后就不再编译,而是提示:“make: `test.out’ is up to date.”
但是当我们把 test.c 中的内容修改过后,我们发现尽管可以再次 make 了,但是仍然不能多次 make
实际上,上面这种现象是 make 为了防止我们对已经编译好且未做修改的源文件重复编译而浪费时间(不要认为编译时间很短);也就是说,如果 test.c 已经编译得到了 test.out,并且我们并没有对 test.c 做改动,那么我们再次 make 时 make 不会被执行;实际上 make 这样做是很有必要的,因为在工作中,编译一个工程往往需要几十分钟甚至几个小时,如果我们 make 每次都重新编译,势必会浪费很多时间。
那么 make 是如何判断源程序不需要重新编译的呢?答案是根据文件的修改时间 (modify time) 来判定。
在Linux中,文件一共有三种时间:stat + 文件名字
访问时间 (Access):当我们查看文件内容后该时间改变,比如 cat、vim、less;
修改时间 (Modify):当我们修改文件内容后改时间改变,比如 nano、vim;
改动时间 (Change):当我们修改文件属性或权限后改时间改变,比如 nano/vim (文件大小改变),chmod/chown/chown (文件权限改变);
make 则是根据可执行程序的修改时间 (modify time) 与源文件的修改时间的对比来判断源程序是否需要重新编译
注:make 判断源文件是否需要重新编译只与源文件的修改时间变动有关,与源文件的内容改动无关,我们可以通过 touch 命令来验证:(touch file:如果 file 已存在,则更新 file 的所有时间)
但是这里touch不是Makefile生成的文件 而是冒号后面的文件 被依赖的文件
所以说:.PHONY 的作用其实和touch很类似,就是修改文件时间,从而使得程序被执行
我们也可以使用 .PHONY 来修饰 test.out,使得 test.out 每次都被重新编译
完结撒花! Linux工具的基本使用到这里告一段落,希望大家多多指点!!!