zoukankan      html  css  js  c++  java
  • 03-Linux命令基础-第03天(makefile、静态库、动态库、gdb调试工具)

    01- 复习

    tar tvf xxx 查看压缩包内容

    区分前后台: 是否能和用户交互

    Vmware选桥接模式 会给系统虚拟一个和外部相同网段的ip

     

     

     

    02- vim扩展操作

    因为不是做嵌入式开发的 所以这些东西不是特别重要

    简单过一遍

    缩进:

    右缩进 两个>>

    左缩进 两个<<

    4行右缩进  4>>

    想把m变量改成n:

    15,17s /f/m/g

    r替换当前字符

    R 替换当前光标后的字符

    [d 查看宏:

     

    (这个宏是在上面定义的)

    在程序中使用man page:

    光标移动到函数身上按K 

    示例:

    这里应该按 3K 查看函数手册页面

    在vim里执行shell命令:

    !ls(在末行模式下)

    :!ls

    :!cp

    :!man

    例如: :!man 2 read

    分屏操作:

    比如我经常在文档开头和文档结尾处编辑 这个时候可以借助分屏

    ctrl+ww

    :sp 分屏 (末行模式)

    ctrl +w  w

    :vsp 竖分屏

    ctrl +w  hjkl 选择性的切换分屏

    :wqall 将所有窗口一次性退出

    分屏打开另外的文件

    :vsp aaa.h

     

    配置文件:

    /etc/vim/vimrc

    这个配置文件配置的是整个操作系统 对所有用户生效

    ~/.vimrc 默认是一个隐藏文件

    … …(如果想设置 自己百度)

    (把vim打造成很强的ide)

    03- gcc编译工具和工具链

    -I 指定头文件的位置:

    hello.c

    hello.h

    mv hello.h ..

    gcc hello.c –I ..

    这样就能编译成功了

    -c只编译 不进行链接

     

    最耗时的操作是编译

    因为编译要一行一行的去检查语法错误

    预处理和汇编都不会检查错误

    汇编只是简单的翻译

    -g 先不讲 后面讲gdb开发再讲

    -On 驱动开发才经常会用

    翻译成汇编的时候会直接删除这段代码

    这段代码指定优化会把中间的没用步骤优化掉

    -Wall ( warning all 提示完整的警告信息)

    例如:

    代码中加了一个不会被使用的变量

    然后gcc hello.c –Wall

    gcc本来就是一个工具链

    GNU编译工具集合器

    符号: 全局变量和函数

    gcc hello.c

    然后可以nm a.out

    描述符T(表示在内存TEXT段内部已经实现的)

    D 是在data段

    U未实现

    gcc –c hello.c

    得到目标文件 hello.o

    nm hello.o

    目标文件比可执行文件 符号少很多

    也就是说在最后一步链接的时候 会像目标文件里链入很多符号表

    printf函数就未实现

    printf函数是一个库函数

    虽然有include <stdio.h>

    但是 printf是在libc库里 libc库是一个动态库

    动态库是在程序的运行期间链接

    只有 ./a.out的时候 才会把printf跟程序链接到一块

    nm 一下之前那个可执行文件 还是U 未实现

    这个主要用于反汇编

     

    例如:

    objdump –dS hello.o

    callq 调用函数

    除了可以反汇编a.o

    也可以反汇编a.out

    ranlib 一般不用 太麻烦了

    elf

    file hello.o:

    LSB 小尾端法存储 低地址存在低字节 高地址存在高字节

    可重定位的

    所以目标文件也叫 可重定位文件

    file a.out:

    可执行文件

    目标文件和可执行文件都是二进制文件

    即使是二进制文件也有属于它的存储格式 即elf格式

    readelf命令就是读取这种格式的工具

    readelf –a hello.o

    大概包括三部分:

    elf头 包括节头

    重定位节:

    符号表:

    可执行程序装载到内存的原理

    64bit系统内存太大了, 从32bit的示例

    0~3G 是用户区

    3G~4G 是kernal区

    text:代码段 存放代码 int main void 什么的ascii码都翻译成二进制

    data: 数据段 常量 字符串

    bss: 未初始化的全局变量和未初始化的static变量

    栈和堆重合的时候就内存溢出了

     

    ro权限 (read only

    rw权限

    text段和data段之间有一个rodata

    04-静态库

    头文件只包含函数声明

    真正的函数是在库文件里面

    静态库libmytest.a

    假如另外的b.out c.out d.out 每个都要添加一份

    会复制一份作为程序代码的一部分

    如果一个3m的静态库 有100个程序使用 内存中就会多出来300MB

    main.c

    add.c

    mul.c

    sub.c

    可以制作成静态库函数

     

    gcc main.c –o app –L ./ -l mymath –I ./

    -L 指定库位置

    -l 指定库的名字

    -I 指定头文件位置

    04- 动态库

    动态链接器

    当运行a.out的时候会使用动态连接器加载

    运行b.out c.out d.out的时候 都会去加载这个stack和heap之间的动态库

    共享代码(不共享数据)的意思是 如果a.out把共享库里一个变量改变了 b.out也会承受这个修改… … 所以一般动态数据库不会共享数据!  (了解)

    动态链接器 链接器 除了名字像没任何关系

    链接器工作在编译阶段

    gcc 生成app的时候会用连接器

    动态链接器是在程序运行的时候装载

    生成可执行文件 然后运行 报错了

    问题出在动态链接器不知道在哪找库

    指定的方法:

    01- 中午复习_动态库

    符号: 全局变量 全局函数

    函数名 变量名 都是地址值

     

    静态库:编译时

    动态库:运行时

     

    Ldd 查看可执行文件执行期间要加载哪些库

    这个东西就是动态链接器

    动态链接器本质也是一个动态库

    .bashrc

     

    类似于vimrc 每次打开终端都会读取这个配置文件

     

    export LD_LIBRARY_PATH = ./   (配置动态链接库目录)

     

    这样配置完每次打开终端都生效

     

     

    动态库的命名:

     

    Realname: libc-2.19.so

     

    这是一个软连接

     

    Linkername : libc.so

     

     

    Soname:

    libc.so.6

    6是大版本号

    Soname的作用 :

    当前是libc-2.19.so

     

    官方进行更新后

    可能变成libc-2.20.so

     

     

    随着版本更新 版本更新的记录不想让用户知道

    防止用户引起恐慌..

    所以使用soname

     

    Soname存在意义就是隐藏内部实现细节

     

     

    静态库)

    nm app:

    Printf mul都没实现

     

    nm app1:

    Mul是已经实现的

     

     

     

    07    gdb调试

     

     

    编译的时候 加 -g 参数

     

    gdb app

     

    list 1 从第一行开始往后列

     

    b 20

     

    info b

    条件断点

    disable

    run 

    p I (print i

    S (step 单步向下执行

    display 

    n next

    s step

    当定义到一个函数的时候就有区别了

    Next会跳过函数 step会跳入函数

     

    ptype

     

     

     

    栈帧:

    函数调用会在栈上进行存储

     

    栈帧:保存局部变量和临时值

     

    局部变量

    临时值:

     

    例:

    函数执行一半执行到mul函数 mul函数执行完了 要回到刚才的位置 所以刚才的位置的地址要保存一下 这个就是临时值

     

    函数只要调用就产生栈帧

     

    当main函数开始调用时 产生一片栈帧,

    执行第一个内部的函数时候 在main下面产生一个栈帧

    当这个函数执行完毕后 这个栈帧消失

    下一个内部函数栈帧生成在main栈帧下面…

     

     

    Bt

    发现两块栈帧

     

     

    Info locals 查看当前栈帧的值

     

     

    段错误 直接Run

    直接运行 然后停止在段错误的代码

     

    08-makefile_x264

     

    Vi makefile

    Vi Makefile

     

    只能起这两个名字 才能使用默认的make命令去执行它

     

     

    Makefile里都是一组一组的规则

     

     

    规则包含三部分:

     

    目标 : 生成目标需要的依赖

          如何生成目标

     

     

    App: add.c sub.c mul.c main.c

         gcc add.c sub.c mul.c main.c

     

     

    Make

     

     

    比如一个main.c有三个依赖,我只修改了一个依赖 我不希望每次都把所有.c都编译

    这时候可以使用makefile

     

    Makefile:

    app: add.o sub.o mul.o main.o

         gcc add.o sub.o mul.o main.o -o app

    add .o: add.c

         gcc -c add.c -o add.o

    sub.o: sub.c

         gcc -c sub.c -o sub.o

    mul.o: mul.c

         gcc -c mul.c -o mul.o

    main.o:main.c

         gcc -c main.c -o main.o

     

     

    然后我修改一个依赖

    然后make , makefile会智能地只编译修改过的c文件

     

     

    .c(依赖)的修改时间比.o(目标)的修改时间晚, 所以需要重新生成目标

     

    重新生成目标后add.o 的修改时间比app晚 所以需要重新生成目标

     

     

     

     

     

     

    然后 make clean

     

     

     

     

    -n 命令 查看执行make的话会做什么

     

    make clean -n

     

    自动变量

    $@

     

    $<

     

    $^

     

    (当$< 和$^ 都可以用的时候 建议用$<    因为后边会用它写模式规则)

    第三个参数中包含第一个参数的部分替换为第二个参数

     

     

    补充小知识:

    %也是通配符

     

     

    现在就可以 向里面加.c 调整.h 而不用调整makefile了

     

    make clean 因为clean得依赖修改时间没有变化(没有依赖)

               所以会提示没有更新

     

    解决方法:

    .PHONY: clean

    把clean 声明称尾目标 不管依赖条件满不满足都会去执行它

     

     

     

    小技巧 rm前面加-

    -rm

    意思是无论是否出错 后序命令都正常执行

     

    因为有时候rm遇到无法删除得文件报错了 后面就都删除不了了

     

     

    当文件不叫makefile得时候要用-f指定

     

    make –f xxxx

     

     

     

    make默认第一条规则是终极目标 如果第一个是完成了 就不往下执行了

    如果想随便掉换行需要指定终极目标

    ALL:app 放在最开始

     

     

    模式规则:

     

     

    静态模式规则:

     

     

    最终版:

     

     

    通常的项目目录

  • 相关阅读:
    利用智能手机(Android)追踪一块磁铁(三)
    利用智能手机(Android)追踪一块磁铁(二)
    利用智能手机(Android)追踪一块磁铁(一)
    android音频发生器
    接口的作用(java)
    Botposter.com集群ETCD2.3.7升级至3.0实录[原创]
    springboot2+jpa+hikari+oracle实战
    Nginx配置详解
    Nginx安装启动+springboot项目实现负载均衡实战
    springboot使用websocket进行实时传送信息实战(包含服务端和客户端)
  • 原文地址:https://www.cnblogs.com/eret9616/p/10775962.html
Copyright © 2011-2022 走看看