Linux工具

目录

软件包管理器yum

        rzsz

        查看软件包

        安装软件

        卸载软件

Vim

                命令模式(command)

                插入模式(insert)

                底行模式(last line)

gcc/g++

        语言和编译器的自举过程

        函数库

        怎么编译

 make/Makefile

                  make是指令,Makefile是文件

        过程实例

        Makefile

进度条

                  缓冲区和换行回车

        倒计时

        进度条

git

        怎么用

gdb


软件包管理器yum

背景:在Linux下安装软件,一般是下载程序的全部源代码,然后编译,运行,得到可执行程序。

但是这种方法的可移植性极低且复杂,所以就有人把常用软件编译运行好之后打包上传到服务器上,用户通过包管理器可以直接获取到软件包。

yum(Yellow dog Updater, Modified)

需要注意:关于yum的所有操作,必须保证主机网络通畅,yum才可以从远程服务器获取下载链接

        rzsz

这是一个linux组件,可以理解为手机上的应用。该工具(软件)用于Windows机器和远端Linux主机通过XShell互传文件。

        查看软件包

yum list | grep lrzsz

软件包名称: 主版本号.次版本号.源程序发行号-软件包的发行号.主机平台.cpu架构.

"x86_64" 后缀表示64位系统的安装包, "i686" 后缀表示32位系统安装包. 选择包时要和系统匹配. 

"el7" 表示操作系统发行版的版本. "el7" 表示的是 centos7/redhat7. "el6" 表示 centos6/redhat6

最后一列, base 表示的是 "软件源" 的名称, 类似于 "小米应用商店", "华为应用商店" 这样的概念

        安装软件

sudo yum install -y lrzsz

安装软件时由于需要向系统目录中写入内容, 一般需要 sudo 或者切到 root 账户下才能完成.
yum安装软件只能一个装完了再装另一个. 正在yum安装一个软件的过程中, 如果再尝试用yum安装另外一个软件, yum会报错.

        卸载软件

sudo yum remove lrzsz

Vim

强大的编辑器

        命令模式(command)

控制屏幕光标的移动,字符、字或行的删除,移动复制某区段及进入Insert mode下,或者到 last line mode

shift + 4 = $:光标定位到当前行最右侧

shift + 6 = ^:光标定位到当前行最左侧

shift + g :定位到文本尾

n + shift +g :定位到第n行

gg:定位到文本开始

H J K L

n yy:复制当前行,加n复制当前行在内的n行

n p:粘贴到下一行,加n粘贴到下面n行

u(undo):撤销刚才的操作

ctrl + r:撤消撤销操作

n dd:删除所在行,加n删除所在行在内的n行

shift + ` = ~:大小写切换

n r:替换光标所指,加n一次性替换多个

shift + r = R:开启替换模式

n x:删除光标所指,加n一次性删除多个

n shift + x = X :删除光标左侧,加n一次性删除多个

w b:跳词改变光标

shift + 3 = # :高亮光标所指单词,可以用n改变光标

shift + zz:ZZ:保存退出

        插入模式(insert)

只有在Insert mode下,才可以做文字输入,按「ESC」键可回到命令行模式。该模式是我们后面用的最频繁的编辑模式。

        底行模式(last line)

文件保存或退出,也可以进行文件替换,找字符串,列出行号等操作。 在命令模式下,shift+: 即可进入该模式。要查看你的所有模式:打开vim,底行模式直接输入:

:help vim-modes

:w保存

:wq保存并退出

:!commend不关闭编辑器强制执行指令 

:vs filename对比某个文件,如果文件不存在,则创建。比较结束,如果直接退出,文件不存在,如果保存退出,文件则存在。命令模式下ctrl +w + w切换光标所在文件

gcc/g++

编译器做的工作:编译链接过程请看另一篇文章

        语言和编译器的自举过程

先有c语言还是先有c语言的编译器?

        先有比c语言低级的比如汇编语言写的c编译器,然后用c语言写一个c编译器,用汇编语言写的c编译器编译,得到用c语言写的c编译器。

        函数库

        在我们的C源代码中,并未定义类似printf的函数,且预编译过程中包含的头文件stdio.h也仅仅只有函数的声明,为什么程序可以正常运行呢?

        系统会把函数的实现打包写入一个库文件,Linux下库的名字是libc.so.6,在没有特别指定的时候,gcc会在系统默认的路径下  /usr/lib/ 下去找库文件,这是一个二进制文件,和编译过程中生成的后缀为.o的可重定位目标二进制文件链接,得到可执行程序

 函数库分为动态库和静态库:

        静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a”
        动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,把类似调用printf函数的地方替换为一个地址,这样可以节省系统的开销。动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件,如下所示。 gcc hello.o –o hello
gcc默认生成的二进制程序,是动态链接的,这点可以通过 file 命令验证

gcc/g++默认使用动态库

怎么安装静态库?

//root用户:
yum install -y glibc-static libstdc++-static

        怎么编译

用cpp源文件举例:

 默认的编译方式是调用动态库:

g++ work.cpp

生成 a.out 的可执行文件

调用静态库:只需加上-static 选项即可

g++ -o b.out work.cpp -static

手动生成b.out的可执行文件

 make/Makefile

像vs2019这样的工具,我们写的大量的文件都会被自动编译,链接,这个过程不需要程序员的参与,这也是集成开发环境的优势。

但是,在原生的环境下,比如我正在使用的云服务器,没有集成开发环境的情况下,写一般的正式项目都会有大量的文件,如何处理他们这个工作由程序员来解决。这个时候需要make/Makefile登场。

        make是指令,Makefile是文件

一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。

makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。


make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。

        过程实例

先写一个源文件

 手动创建Makefile或者makefile

然后配置Makefile

如何配置:

        依赖关系和依赖方法

result:task.c这一行叫做依赖关系,result叫做目标文件,task.c叫做依赖文件列表(或依赖多个文件)

紧跟的一行叫做依赖方法,需要用Tab键缩进

使用 make指令即可生成项目

 如果再次make

因为没有修改源文件,生成的项目不会发生改变,所以make工具不会再自动构建项目。

在Makefile配置新的目标

 再make前用clean,类似vs2022的清理已经生成的项目

 如果这样写Makefile

 

makefile和make形成目标文件的时候,默认形成第一个目标文件

默认只形成一个

如你所见,使用make重复编译是被不允许的,但是我们可以自己手动使用gcc编译,那么make和Makefile是如何判断源文件是否修改过,需要编译呢?

        AMC时间

        广义来说,文件 = 内容 + 属性。

        Access time:最近一次访问文件的时间,但是由于实际过程中经常访问文件,所以,这个时间的变化不会很确定。

        Modify time:最后一次修改文件内容的时间

        Change time:最后一次修改文件属性的时间,上图的例子中修改文件内容的同时,文件的大小也会发生变化,所以chang time 也会随之改变

        而make和makefile是通过对比源文件和可执行程序的Modify时间来决定是否需要编译的

比如task.c和相对应的result

Makefile

.PHONY修饰伪目标

在.PHONY 定义的伪目标中,那就直接在Makefile中就执行伪目标的依赖和命令。不管Makefile同级目录下是否有该伪目标同名的文件,即使有也不会产生冲突。另一个就是提高执行makefile时的效率

自定义变量

 语法推导

进度条

        缓冲区和换行回车

c语言有缓冲区这一概念

                                                                                                              
  1 #include <stdio.h>
  2 #include <unistd.h>
  3 
  4 int main(void)
  5 {
  6   printf("1111     \n");
  7   sleep(2);
  8   return 0;                                                                                                               
  9 }                                                                                                                                                             
  1 #include <stdio.h>
  2 #include <unistd.h>
  3 
  4 int main(void)
  5 {
  6   printf("1111    ");                                                                                                                                             
  7   sleep(2);
  8   return 0;
  9 }

代码一的结果是因为\n刷新了缓冲区。在第二个代码片段中,实际上需要打印的内容被保存了起来,但是没有刷新缓冲区。 

\r回车 即光标回到当前行开头,且删除行内容

\n换行,跳到下一行对应位置

倒计时

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 
  4 int main(void)
  5 {
  6   int i = 10;
  7   while(i>= 0)
  8   {
  9     printf("%-2d\r",i);
 10     fflush(stdout);                                                                                                                                               
 11     i--;
 12     sleep(1);
 13   }
 14   return 0;
 15 }
~
~
~

进度条

//这只是单纯写了一个进度条样式
void processbar2()
 19 {
 20   char buffer[NUM];
 21   memset(buffer,0,sizeof(buffer));
 22 
 23   int count = 0;
 24   int n = strlen(LABEL);
 25   buffer[0] = HEAD;
 26   while(count <= 100)
 27   {
 28     printf("[%-100s][%3d%%][%c]\r",buffer,count,LABEL[count%n]);
 29     fflush(stdout);                                                                                                                                               
 30     buffer[count++] =BODY;
 31     if(count < 100) buffer[count] = HEAD;
 32     usleep(100000);
 33   }
 34   printf("\n");
 35 }

 真正的进度条必然和某个东西关联,比如下载,解压。这个代码很麻烦,我这里只讲需要注意的东西,为什么这样写,要怎么写,顺便理清我的思路。

        先模拟一个下载场景

文件总大小FILESIZE 一个G,用一个变量total表示剩余下载量,用循环,表示当剩余下载量为0对时候,结束下载,用一个变量one模拟每次的下载量,用随机数来模拟,这里模拟每次下载5M,每次下载,剩余下载量就会减小,因为是随机数模拟,无法保证FILESIZE可以减小到0,所以加一个判断。用一个变量表示下载量,用一个变量表示比率,即下载了百分之多

少,OK,下载场景模拟完了。

#define FILESIZE 1024*1024 
void download()
    8 {
    9   int total = FILESIZE;
   10   srand(time(NULL)^1023);//随机数种子
   11   while(total)
   12   {
   13     int one = rand()%(1024*5);
   14     total -= one;
   15     if(total < 0) total = 0;
   16 
   17     int download = FILESIZE - total;
   18     double rate = (download*1.0 / FILESIZE)*100;
   19    // printf("%f\n",rate);
   20   
   21     usleep(10000);                                                                                                                                              
   22   }
   23 }

         然后将每次的下载量用进度条的形式表示出来即可,然后回车就行。

 直接说,这个实现的进度条:

1.他的“下载速度”是1%,如果你增大上段代码的one,即每次下载量,比率rate会跳跃式变化,所以下面这段代码的赋值会出现问题,总而言之,这里实现的进度条就是模拟每次只能下载1%。

2.光标不和下载百分比挂钩,即你下载速度可能慢,但是光标一直在变化

OK,buffer数组定义为全局变量,你不能每次调用这个进度条,都开一个数组,用单独一个变量count来表示光标的变化。用# 来画这个进度条,打印只打印100个字符,即这个数组的下标0 - 99,fflush将打印内容刷新出来。

#define SIGN '#'
void processbar_flush(double rate)
 38 {
 39   static int count = 0;
 41 
 42   printf("[%-100s][%.1f%%][%c]\r",buffer,rate,LABEL[count%4]);
 43   fflush(stdout);
 44 
 45   buffer[(int)rate] = SIGN;
 46                                                                                                       
 48   if(rate >= 100.00 ) printf("\n");
 49   count++;
 50   count %= 4;
 51 }

git

        怎么用

gdb

        程序最后有两种发行模式,一种是release,也叫发行版,一般用来测试,该程序不包含调试信息;一种是debug模式,包含调试信息。gcc默认编译的结果是release版,所以为了调试需要加-g选项

 gcc -o mytest test.c -g 

        所有的调试器都是为了帮助我们发现程序的问题,所以gdb的指令可以类比vs2019的调试功能来理解。 

list或者l 行号:显示源文件代码,每次显示10行

list或者l 函数名:显示函数的源代码

run或者r:运行程序

break或者b 行号/函数名/文件:行号:打断点

next或者n:类比vs2019 F10,执行一行

step或者s:类比vs2019 F11,执行一句

info break或者b:显示断点信息

delete或者d n:删除编号为n的断点

disable/enable n:使能编号为n的断点

——

print或者p 变量:打印

display 变量:常显示

undisplay 编号:取消常显示

continue或者c:从一个断点运行到下一个断点

finish:将当前函数运行结束

until:运行到第n行,前提是合法的

breaktrace或者bt:调用堆栈

set var name=value:临时修改name的值为value,执行某一个分支,不修改源代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值