Linux软件包安装管理

yum

在(iphone)手机上安装软件wecheat通过在appstore上搜索wecheat下载安装;在windows下安装软件可以在wecheat官网上下载安装。

但是在Linux环境下安装软件却复杂的多,一般来说有三种方式:

  • 源码安装:下载源码,自己修改、安装;
  • rpm包安装;
  • yum安装;

但是前两种方式并不简单,而yum安装就相当于yum是手机中的AppStore,用过yum来搜索、安装软件极为方便。


如何安装软件:

在Linux环境下 yum list | grep lrzsz 筛选软件找到 lrzsz 软件,在通过 sudo yum install lrzsz 完成安装操作,或 sudo yum -y install lrzsz

如何卸载软件:

以刚才的lrzsz为例,sudo yum remove lrzsz 即可卸载 lrzsz 软件。


如上图,使用yum搜索lrzsz软件;

如上图,安装lrzsz软件;

lrzsz的用处在于:上传windows环境下的文件:

如上图,当lrzsz安装完成后,输入rz指令会自动打开文件目录,选择需要上传的文件即可;或者直接将需要上传的文件拖拽至xshell程序框也可。

 vim

vim简单的来说就是一个功能强大的编辑器;

安装vim: sudo yum install -y  vim ;

查看是否安装成功:输入 vim 以直接进入vim,按住shift并输入:后再输入q即可退出vim;

如上图,输入vim后显示这个即表示安装成功。


在vim中,有三种模式:

  1. 命令模式,也是默认模式;
  2. 插入模式,该模式下编写代码;
  3. 底行模式;

使用 vim 文件名 进入到代码编译模式,在进入到编译环境下,默认是命令模式,输入i进入到插入模式,同时,左下角也会显示insert字样,如下图所示:


接下来使用如下代码介绍一些基本的文本操作:

  1. yy / n+yy:光标停在代码行前面,输入yy,表示复制光标当前所在行;n+yy表示复制从光标所在行后面的n行代码。
  2. dd / n+dd:光标停在代码行前面,输入dd,表示剪切光标当前所在行;n+dd表示剪切光标所在行后面的n行代码;这个操作也可用来删除。
  3. p / n+p:表示粘贴刚才复制 / 剪切的内容;n+p表示将内容粘贴n行;
  4. u:表示撤销刚才的操作;
  5. ctrl+r:表示撤销刚才u的操作;
  6. shift+g:表示光标快速定位到文本末尾;
  7. gg:表示光标快速定位到文本开头;
  8. n+shift+g:表示光标快速定位到第n行;
  9. r+目标字符:表示将光标r所在的字符替换成目标字符;
  10. nr+目标字符:表示将n个字符替换成目标字符;
  11. x / nx:表示删除光标所在的字符;nx表示批量化删除光标后的n个字符;
  12. h j k l:表示光标左、下、上、右移动;

各个模式的转换:

底行模式到插入模式一般是底行模式先到命令模式再到插入模式;

gcc的编译过程

gcc(g++) text.c -o mytext;

将c代码编译成指定文件名mytext,如上图可以看出g++既可以编译c++代码,也可以编译c代码,但是gcc只能编译c代码。

如上图,使用vim编写代码;

预处理

gcc -E test.c -o test.i;

使用如上代码:

  • -E表示从现在开始对程序进行编译,当预处理完成后就停下来;
  • -o表示将编译的文件保存在test.i文件中;

如上图,在编译完成后的test.i文件中,可以看见,源代码的注释、头文件、条件编译被消除,相对来说,代码更加简短。


编译

gcc -S text.i -o text.s;

使用如上指令,

  • -S:表示从现在开始程序的翻译,汇编结束之后就停下来;

在我们查看text.s代码后看见,这是汇编语言代码,我们无法阅读的。


汇编

汇编是将汇编语言代码翻译成二进制文件,这是一种可重定位的二进制文件(o/.obj结尾)。

gcc -c text.s -o test.o; 使用上述指令形成二进制代码

  • -c:表示从现在开始翻译,当汇编结束后就结束。

如上图,生成了text.o文件(二进制文件),如果需要查看需要对应的二进制转换器,如果直接打开会是乱码;如下图所示:


此时两个问题:

  • text中的代码没有printf函数的实现;
  • text中的printf函数怎么和库函数中的printf函数关联;

链接

gcc text.o -o mytext;

使用上述指令将编写的代码与c标准库进行关联,即可运行。

函数库的概念

函数的库分为静态库和动态库两种:

  • 静态库在编译链接时将库文件中的代码全部加载到可执行文件中,因此这个文件非常大,但在后期运行时也就不需要库文件了,后缀是 ‘ .a ’;
  • 动态库在编译链接时没有将库文件的代码加载到可执行文件中,而是在程序运行时由链接文件加载库,gcc编译器就是动态链接,这样可以节省系统的开销,后缀是 ' .s '

ldd 文件名;

上述指令用来查看文件的链接属性;

如上图,这里的lib.c.so.6就是一个动态库;

修改静态链接:

gcc 文件名 -o 生成文件名 -static;

如上图所示,动态链接的文件比静态链接的文件要小很多,而且一般来说,编译环境也没有自带静态库。因此需要我们自己安装:指令如下,第一个是c静态库,第二个是cpp静态库:
sudo yum install -y glibc-static;

sudo yum install -y libc++-static;

gdb

编译如下代码:

gdb 可执行文件名;

使用上述指令对可执行文件进行调试,会出现如下:无调试符号;这是因为在linux下程序默认是release版本的,也就是说在linux环境下程序可以直接发布,

gcc 可执行文件名 -o 生成文件名 -g;

上述代码就表示用debug的方式调试代码,但是注意的是生成的 text1_debug 和 text1 都是可执行文件,但是 text1_debug 明显比 text1 要大些:因为 text1_debug 中存有调试信息。


演示gdb调试细节:

[asy@VM-8-10-centos dir1]$ touch test1.c
[asy@VM-8-10-centos dir1]$ vim test1.c
[asy@VM-8-10-centos dir1]$ gcc test1.c -o mytest1_debug -g
[asy@VM-8-10-centos dir1]$ ll
total 16
-rwxrwxr-x 1 asy asy 9568 Dec  3 11:03 mytest1_debug
-rw-rw-r-- 1 asy asy  168 Dec  3 11:01 test1.c

使用gcc test1.c -o mytest1_dubug -g; 生成可调式的代码文件;


[asy@VM-8-10-centos dir1]$ ll
total 16
-rwxrwxr-x 1 asy asy 9568 Dec  3 11:03 mytest1_debug
-rw-rw-r-- 1 asy asy  168 Dec  3 11:01 test1.c
[asy@VM-8-10-centos dir1]$ gdb mytest1_debug
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/asy/Linux/2023-11-03/dir1/mytest1_debug...done.
(gdb) l 0
1	#include <stdio.h>
2	
3	int Add(int x1,int x2){
4	  return x1+x2;
5	}
6	
7	int main(){
8	  int a = 10;
9	  int b = 20;
10	  int sum =  Add(a,b);
(gdb) 
11	  printf("sum = %d\n",sum);
12	  return 0;
13	}
(gdb) 

gdb mytest1_debug; 进入调试模式  ——>  L 0 回车;  打印代码信息;


(gdb) b 8
Breakpoint 1 at 0x400549: file test1.c, line 8.
(gdb) b 9
Breakpoint 2 at 0x400550: file test1.c, line 9.
(gdb) b 10
Breakpoint 3 at 0x400557: file test1.c, line 10.
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000400549 in main at test1.c:8
2       breakpoint     keep y   0x0000000000400550 in main at test1.c:9
3       breakpoint     keep y   0x0000000000400557 in main at test1.c:10
(gdb) 

b 行号;  为代码添加断点;  info b;  显示全部断点的位置;


(gdb) r
Starting program: /home/asy/Linux/2023-11-03/dir1/mytest1_debug 

Breakpoint 1, main () at test1.c:8
8	  int a = 10;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.x86_64

r ;  将代码运行到断点处;


(gdb) s
Breakpoint 2, main () at test1.c:9
9	  int b = 20;

(gdb) s
Breakpoint 3, main () at test1.c:10
10	  int sum =  Add(a,b);

(gdb) 

s ;  代码逐语句运行;


(gdb) p a
$5 = 10
(gdb) p b
$6 = 20
(gdb) p sum
$7 = 30
(gdb) 

p  (&)变量;  打印当前变量的 值 / 地址;


(gdb) s
0x00007ffff7a2f555 in __libc_start_main () from /lib64/libc.so.6
(gdb) s
Single stepping until exit from function __libc_start_main,
which has no line number information.
[Inferior 1 (process 24803) exited normally]
(gdb) 

本次调试结束。

Breakpoint 3 at 0x400569: file test1.c, line 11.
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000400549 in main at test1.c:8
2       breakpoint     keep y   0x0000000000400557 in main at test1.c:10
3       breakpoint     keep y   0x0000000000400569 in main at test1.c:11
(gdb) 

 依旧是原先的代码,这一次演示如下操作:

  1. n;逐过程,可以跳过Add函数内部执行过程;
  2. d 断点编号;去除断点;
  3. Display 变量名;每次调试时都打印该变量的值;
  4. Undisplay 变量编号;取消变量的打印;
  5. Until 行号;直接跳转到该行调试;
  6. c;直接跳转到下一个断点处运行;
  7. Finish;执行完一个函数就停下来;
(gdb) r
Starting program: /home/asy/Linux/2023-11-03/dir1/mytest1_debug 

Breakpoint 1, main () at test1.c:8
8	  int a = 10;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.x86_64
(gdb) c
Continuing.

Breakpoint 2, main () at test1.c:10
10	  int sum =  Add(a,b);
(gdb) 

如上代码,进入调试时代码在8断点位置,输入 ' c ' 指令,代码直接运行到下一个断点10的位置;


(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000400549 in main at test1.c:8
2       breakpoint     keep y   0x0000000000400557 in main at test1.c:10
3       breakpoint     keep y   0x0000000000400569 in main at test1.c:11
(gdb) d 3
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000400549 in main at test1.c:8
2       breakpoint     keep y   0x0000000000400557 in main at test1.c:10
(gdb) 

如上代码,d 断点编号;  删除断点;


(gdb) Display a
1: a = 0

(gdb) Display b
2: b = 0

(gdb) s
9	  int b = 20;
2: b = 0
1: a = 10

(gdb) Undisplay 1

(gdb) s
Breakpoint 2, main () at test1.c:10
10	  int sum =  Add(a,b);
2: b = 20

(gdb) 

如上代码,Display 变量名;Undisplay 变量编号;


(gdb) r
Starting program: /home/asy/Linux/2023-11-03/dir1/mytest1_debug 

Breakpoint 1, main () at test1.c:8
8	  int a = 10;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.x86_64

(gdb) until 10
main () at test1.c:10
10	  int sum =  Add(a,b);

(gdb) 

如上代码,until 行号;代码直接运行到该行;


(gdb) b 8
Breakpoint 1 at 0x400549: file test1.c, line 8.
(gdb) b 11
Breakpoint 2 at 0x400569: file test1.c, line 11.

(gdb) r
Starting program: /home/asy/Linux/2023-11-03/dir1/mytest1_debug 

Breakpoint 1, main () at test1.c:8
8	  int a = 10;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.x86_64

(gdb) c
Continuing.

Breakpoint 2, main () at test1.c:11
11	  printf("sum = %d\n",sum);

(gdb) 

如上代码,在第8行、11行添加断点,进入调试后先来到第8行,输入 c ;直接运行到下一断点处。

make/makefile

nake是一个命令,而makefile是一个文件,在这个文件中包含依赖关系与依赖方法;在下面的这个实例演示中,

  • test1.c ———(生成)———>mytest1_makefile;叫做依赖方法;
  • mytest1_makefile———(生成)———>test1.c;叫做依赖途径;

就比如张爸和张三的生活费例子,因此只要我们表明依赖关系与依赖方法就能形成可执行程序

实例演示:

以下通过上述代码实例演示依赖关系与依赖方法:

[asy@VM-8-10-centos dir1]$ ll
total 16
-rwxrwxr-x 1 asy asy 9568 Dec  3 11:03 mytest1_debug
-rw-rw-r-- 1 asy asy  168 Dec  3 11:01 test1.c

[asy@VM-8-10-centos dir1]$ touch Makefile

[asy@VM-8-10-centos dir1]$ vim Makefile

如上代码,创建一个Makefile文件,并使用vim进入编辑页面


[asy@VM-8-10-centos dir1]$ cat Makefile
mytest2_makefile:test1.c
	gcc test1.c -o mytest2_makefile

如上代码,对Makefile的编辑内容如上代码所示;


[asy@VM-8-10-centos dir1]$ make

gcc test1.c -o mytest2_makefile
[asy@VM-8-10-centos dir1]$ ll
total 32
-rw-rw-r-- 1 asy asy   58 Dec  3 12:15 Makefile
-rwxrwxr-x 1 asy asy 9568 Dec  3 11:03 mytest1_debug
-rwxrwxr-x 1 asy asy 8384 Dec  3 12:16 mytest2_makefile
-rw-rw-r-- 1 asy asy  168 Dec  3 11:01 test1.c

[asy@VM-8-10-centos dir1]$ ./mytest2_makefile
sum = 30

如上代码,此时我调用 make 指令会根据makefile内部的指令来自动生成 " mytest2_debug " 的可执行文件,这里的make是一个指令,而makefile是一个文件。

项目清理:

在刚才演示的mytest2_makefile代码操作中产生的工程需要被清理,打开刚才的Makefile文件并编辑代码:

  1 mytest2_makefile:test1.c
  2   gcc test1.c -o mytest2_makefile
  3 
  4 .PHONY:clean
  5   rm -f mytest2_makefile                                                                                                                                                                 
  6 

使用指令 " make clean " 即可清理工程。

详解依赖关系与依赖方法:

如上图所示,

  • 在Makefile文件中 mytest2_makefile 是目标文件,他的生成依赖源文件 test1.c ,并且还依赖 "gcc test1.c -o mytest2_makefile" 这个依赖方法。在我使用make指令时,make指令总是默认执行的是形成第一个目标文件(一般来说将生成的可执行文件放在第一位)。
  • 而对于clean来说,“ PHONY ”可以理解成makefile里面的关键字,其含义是:凡是被PHONY修饰的目标,总是 “ 被执行的 ” 。【当然这很难理解,接着看:】

接下来我进行实操:

如上图,当编写完成test1.c的代码时,使用make指令生成mytest2_makefile可执行文件,当我想再次make时会发现系统显示 “ mytest2_makefile已是最新的 ” 。这是 “ 不是总是被执行的”。

那什么叫 “ 总是被执行 ” 的呢?

如上图,使用 " make clean " 指令对生成的项目进行清理时,可以看见系统可以进行多次的执行,而不同于make生成了可执行文件后就不再执行。这就是 “ 总是被执行 ”。

如上图,当我们使用 " .PHONY " 修饰 mytest2_makefile 时,也可以对其进行对此调用,此时系统就会重新生成可执行文件。


那么回到刚才的话题,如果PHONY没有修饰mytest2_makefile时,系统如何知道什么时候需要生成新的可执行文件呢?或者说当源代码发生修改此时就需要更新可执行文件,那系统是如何知道的呢?

如上图,在OS中,文件由 “内容” 和 “属性” 两部分组成,这里我们需要先认识 “ Modify ” 和 “ Change ”:

  • Modify:表示文件内容的修改;
  • Change:表示文件属性的修改;
  • 注意:内容修改也可能会引起属性的修改,如文件内容的变动影响文件的大小。

弄清楚这两点后就可以弄清楚OS如何知道什么时候生成新的可执行程序了。

如上图,test1.c和mytest1_makefile的时间,test1.c在mytest1_makefile时间之前,或者说生成的可执行文件是在源文件修改之后生成的,也就是最新的,因此这也就能解释前面提到的多次make时会显示 “make mytest_makefile is up to data "【当然此时是不在PHONY修饰的前提下】。

如上图,在经过几分钟后,使用touch指令更新test1.c的时间,此时可以看见test1.c的时间在mytest1_makefile时间之后,也就是说,生成的可执行文件是旧版的,不是源代码修改之后生成的最新版本的。因此此时再次make就不会出现 “make mytest_makefile is up to data "的情况。

如上图,再次生成的可执行文件时间也是有所变化的。

至于Access,单次的文件访问对于Access不会有太大的影响,因为在OS中文件的访问次数要远远高于文件的修改次数,如果要更新Access将会消耗大量的OS资源,因此只有当访问次数达到一定数量后,此时Access才会发生改变。

总结:

通过对比文件的modify和change时间来决定是否需要重新生成可执行文件。

接下来演示多个文件的操作:

如上图,创建的三个文件分别对应不同的代码内容。

如上图,在第一行时,此时并没有生成main.o和test.o文件,此时OS会继续往下走,找到main.o和test.o对应的依赖关系和方法,此时在回过头来生成mytest2_makefile。

  • 在clean中,*表示通配符,表示将所有以.o结尾的文件删除。
  • 23
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值