Linux:软件包管理器yum、编辑器vim、编译器gcc/g++、调试器gdb的使用

yum

首先关于yum的操作要在主机(虚拟机)网络畅通下进行,通过ping指令验证
1、查看软件包:yum list、yum list installed(查看已安装的软件包)、yum list | grep lrzsz(使用grep命令筛选)
2、安装软件:在root用户下,yum install lrzsz即可
3、卸载软件:yum remove lrzsz(在root下)

Linux编辑器vim
  • vim的模式
    vim一共有12种模式,常用的有3种,所有模式都是围绕普通模式切换的
    3种模式分别为普通模式、插入模式、末行模式
  • vim的基本操作
    1、进行vim 文件名操作就可以进入vim下,处于普通模式,要切换到插入模式才可以进行输入
    2、退出vim(在普通模式下)
    :w表示保存当前文件;:wq表示存盘并退出;:q!表示不存盘强制退出
  • vim普通模式命令
    1、插入模式:
    (1)按 i 按键进入插入模式,表示从光标当前位置开始输入文件
    (2)按 a 按键进入插入模式,表示从目前的光标所在位置的下一个位置开始输入文字
    (3)按 o 按键进入插入模式,表示插入新的一行,从行首开始输入文字。
    2、从插入模式转换到普通模式:按Esc按键
    3、从普通模式转换到末行模式:按shift+;按键,也就是 :号
    4、移动光标
    (1)使用 hjkl 四个按键进行左下上右的移动
    (2)按G移动到文章最后,按w移动到下个字的开头,按e移到下个字的字尾,按b移到上个字的开头,按gg进入到文本开始,按ctrl+b屏幕向后移动一页,按ctrl+f屏幕向前移动一页,按ctrl+u屏幕向后移动半页,按ctrl+d屏幕向前移动半页
    5、删除文字
    (1)x:每按一次,删除光标所在位置的一个字符
    (2)#x:例如 7x表示删除光标所在位置的后面(包括自己)的7个字符
    (3)X:大写的X,每按一次,删除光标所在位置的前面一个字符
    (4)#X:例如:7X表示删除光标所在位置的前7个字符
    (5)dd:删除光标所在行
    (6)#dd:从光标所在行开始删除#行
    6、复制
    (1)yy:复制光标所在行
    (2)p:粘贴到光标所在位置
    (3)yw:将光标所到之处到字尾的字符复制
    (4)#yw:复制#个字
    7、替换
    (1)r:替换光标所在处的字符
    (2)R:替换光标所到之处的字符
    8、撤销上一次操作
    (1)u:回到上一个操作
    (2)ctrl+r:撤销的恢复
    9、更改
    (1)cw:更改光标所到处的字到字尾处
    (2)c#w:例如c5w表示更改5个字
    10、代码对齐:
    gg=G进行代码对齐。
  • vim末行模式命令
    1、列出行号:set nu 在进入末行模式后,输入set nu会出现行号
    2、调到文件的某一行:# :#号表示一个数字,例如在进入末行模式后,输入14会跳到14行
    3、查找字符
    (1)/关键字:如果第一次找的关键字不是想要的,按n键向后找
    (2)?关键字:如果第一次找的关键字不是想要的,按n键向前找
    4、保存文件(w键)
    5、离开vim(wq和q!)
    6、%s 文件名1 文件名2表示用文件名2替换文件名1(加上g命令表示全部替换)
    7、!man表示直接在vim末行模式下查询
Linux编译器gcc/g++
  • gcc生成代码结果的过程
    1、预处理阶段(宏替换)
    预处理阶段包括宏定义、文件包含、条件编译、去除注释等
    例如:
[Daisy@localhost ~]$ clear
[Daisy@localhost ~]$ ls
file.txt  main.c  公共  模板  视频  图片  文档  下载  音乐  桌面
[Daisy@localhost ~]$ vim main.c

进入vim编辑器下,然后在vim下输入代码,例如:


#include <stdio.h>
void func()
{
        int i=0;
        for(i=0;i<10;i++)
        {
                printf("hello bite\n");
        }
        return;
}
int main()
{
        func();
        printf("hello world\n");
        return 0;
}

之后进行gcc -E main.c -o main.i进行预处理生成main.i文件
例如:

[Daisy@localhost ~]$ gcc -E main.c -o main.i
[Daisy@localhost ~]$ ls
file.txt  main.c  main.i  公共  模板  视频  图片  文档  下载  音乐  桌面

进入main.i的vim下,显示

# 1 "main.c"
# 1 "<built-in>"
# 1 "<命令行>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<命令行>" 2
# 1 "main.c"

# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 375 "/usr/include/features.h" 3 4
# 1 "/usr/include/sys/cdefs.h" 1 3 4
# 392 "/usr/include/sys/cdefs.h" 3 4
# 1 "/usr/include/bits/wordsize.h" 1 3 4
# 393 "/usr/include/sys/cdefs.h" 2 3 4
# 376 "/usr/include/features.h" 2 3 4
# 399 "/usr/include/features.h" 3 4
# 1 "/usr/include/gnu/stubs.h" 1 3 4
# 10 "/usr/include/gnu/stubs.h" 3 4
# 1 "/usr/include/gnu/stubs-64.h" 1 3 4
# 11 "/usr/include/gnu/stubs.h" 2 3 4
# 400 "/usr/include/features.h" 2 3 4
# 28 "/usr/include/stdio.h" 2 3 4





# 1 "/usr/lib/gcc/x86_64-redhat-linux/4.8.5/include/stddef.h" 1 3 4
# 212 "/usr/lib/gcc/x86_64-redhat-linux/4.8.5/include/stddef.h" 3 4
typedef long unsigned int size_t;
# 34 "/usr/include/stdio.h" 2 3 4

# 1 "/usr/include/bits/types.h" 1 3 4
"main.i" 853L, 16959C       

说明进行了预处理操作
2、编译阶段(生成汇编)
这个阶段是进行语义语法纠错,如果没有错误,将高级语言生成汇编语言
对上述生成的main.i文件进行gcc -S main.i -o main.s操作,生成main.s文件,例如:

[Daisy@localhost ~]$ gcc -S  main.i -o main.s
[Daisy@localhost ~]$ ls
file.txt  main.c  main.i  main.s  公共  模板  视频  图片  文档  下载  音乐  桌面

vim main.s,显示

       .file   "main.c"
        .section        .rodata
.LC0:
        .string "hello bite"
        .text
        .globl  func
        .type   func, @function
func:
.LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $16, %rsp
        movl    $0, -4(%rbp)
        movl    $0, -4(%rbp)
        jmp     .L2
.L3:
        movl    $.LC0, %edi
        call    puts
        addl    $1, -4(%rbp)
.L2:
        cmpl    $9, -4(%rbp)
        jle     .L3
        nop
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   func, .-func
        .section        .rodata
"main.s" 60L, 915C     

这里就是对代码进行检查,检查无误后,将代码翻译成汇编语言
3、汇编阶段(生成机器可识别代码)
这个阶段是将编译阶段生成的汇编代码main.s文件转成目标文件
使用gcc -c main.s -o main.o命令,例如:

[Daisy@localhost ~]$ gcc main.s -o main.o
[Daisy@localhost ~]$ ls
file.txt  main.c  main.i  main.o  main.s  公共  模板  视频  图片  文档  下载  音乐  桌面

vim main.o显示二进制文件,如图(因文件显示太多,故截屏)
在这里插入图片描述
4、链接阶段(生成可执行文件或者库文件)
在编译后,进入链接阶段使用gcc main.o -o main,即将所有文件代码以及库文件中的代码集合打包成可执行程序,即生成main文件(可执行文件)
例如:

[Daisy@localhost ~]$ gcc main.o -o main
[Daisy@localhost ~]$ ls
file.txt  main  main.c  main.i  main.o  main.s  公共  模板  视频  图片  文档  下载  音乐  桌面

最后对main文件进行编译,可得

[Daisy@localhost ~]$ ./main
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello world

即代码结果
在这里我们可以看到在执行程序时,程序需要被加载到内存中,若多个程序使用了相同的库,则内存中就出现了大量的库函数代码冗余,这时没有必要的,完全可以让相同的库函数代码在内存中只加载一次,不需要多份,大家共享使用,因此链接方式有两种:静态链接和动态链接

  • 函数库
    静态链接:把库函数的代码全部加入到可执行文件中,它的优点是可以不依赖库函数的存在,库文件被删除依然可以运行;它的缺点是若库文件被大量的程序使用,运行时会造成大量的内存中代码冗余(静态链接链接静态库)
    动态链接:链接生成可执行程序时,并不拷贝代码,只是在可执行程序中记录函数位置符号信息,等到运行时将库加载到内存中,并且多个程序可以共享使用,它的优点是节省系统开销,但是程序运行时,库函数必须存在(动态链接动态库)
    注意:gcc默认生成的二进制程序,是动态链接的。
Linux调试器gdb

gdb调试的前提是使用gcc/g++生成debug版本可执行程序
但是gcc/g++出来的二进制程序,默认是release版本的,需要加上-g选项
例如:
gcc -g main.c -o main
gdb ./main是加载程序调试,例如

[Daisy@localhost ~]$ gdb ./main
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-115.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/Daisy/main...done.
(gdb) 

显示Reading symbols from /home/Daisy/main…done.表示调试

  • 逐步调试
    start指令表示开始调试,例如:
(gdb) start
Temporary breakpoint 1 at 0x400560: file main.c, line 14.
Starting program: /home/Daisy/./main 

Temporary breakpoint 1, main () at main.c:14
14		func();
Missing separate debuginfos, use: debuginfo-install glibc-2.17-196.el7.x86_64

其中14表示函数func开始调用
list(如果有多个文件,使用list 文件名:行号)指令表示查看调试行附近代码,例如:

(gdb) list
9		}
10		return;
11	}
12	int main()
13	{
14		func();
15		printf("hello world\n");
16		return 0;
17	}

然后next(n)指令表示下一步(不进入函数),例如:

(gdb) next
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
15		printf("hello world\n");

可以看出没有进入函数,直接将函数运行并走到下一步
若使用step指令表示下一步并且跟踪进入函数,例如

(gdb) step
func () at main.c:5
5		int i=0;
(gdb) step
6		for(i=0;i<10;i++)
(gdb) step
8			printf("hello bite\n");
(gdb) step
hello bite
6		for(i=0;i<10;i++)
(gdb) step
8			printf("hello bite\n");

可以看出在执行函数中的循环,说明进入了函数
continue指令表示从当前位置开始直接运行程序,例如:

(gdb) continue
Continuing.
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello world
[Inferior 1 (process 4045) exited normally]

表示程序运行完毕
until 文件名 :行号表示运行到某个文件某一行,例如:

(gdb) until main: 14
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello world
0x00007ffff7a39c05 in __libc_start_main () from /lib64/libc.so.6

程序直接运行到第14行
run指令表示直接运行程序,例如:

(gdb) run
Starting program: /home/Daisy/./main 
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello world
[Inferior 1 (process 4111) exited normally]
  • 断点调试
    break(b) 文件名:行号指令表示在某一个文件的某一行打断点
    例如:
(gdb) break main.c:13
Breakpoint 1 at 0x400560: file main.c, line 13.

已经显示在13行打了一个断点
break 函数名指令表示直接对函数打断点
例如:

(gdb) break func
Breakpoint 2 at 0x400535: file main.c, line 5.
(gdb) list main.c:5
1	
2	#include <stdio.h>
3	void func()
4	{
5		int i=0;
6		for(i=0;i<10;i++)
7		{
8			printf("hello bite\n");
9		}
10		return;

通过list命令可以看到对指定func函数打了断点
info break指令表示查看断点信息,例如:

(gdb) info break
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000400560 in main at main.c:13
2       breakpoint     keep y   0x0000000000400535 in func at main.c:5

delete指令表示删除断点,delete+第几个断点表示删除哪个断点,例如:

(gdb) delete 1
(gdb) info break
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x0000000000400535 in func at main.c:5

watch 变量指令表示变量监控断点,例如:

(gdb) n
Breakpoint 2, func () at main.c:5
5		int i=0;
(gdb) watch i
Hardware watchpoint 3: i

先让代码走到有i变量的地方,可以通过watch 变量指令来表示变量监控断点
print(p)变量指令表示打印变量内容,例如:

(gdb) print i
$1 = 0
  • 其他调试
    例如将main.c改成
#include <stdio.h>
#include <string.h>
void func()
{
        int i=0;
        for(i=0;i<10;i++)
        {
                printf("hello bite\n");
        }
        char* ptr=NULL;
        memcpy(ptr,"hello",5);
        return;
}
int main()
{
        func();
        printf("hello world\n");
        return 0;
}

对他进行编译,然后利用gdb进行调试,例如:

(gdb) run
Starting program: /home/Daisy/./main 
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite
hello bite

Program received signal SIGSEGV, Segmentation fault.

发现显示有错误
但是此时不知道哪里有错误,输入backtrace指令(查看函数调用栈),例如:

(gdb) backtrace
#0  0x00007ffff7b5d1a6 in __memcpy_ssse3 () from /lib64/libc.so.6
#1  0x00000000004005e7 in func ()
#2  0x00000000004005f8 in main ()

当程序运行崩溃了,使用backtrace来查看函数调用栈。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值