0%

昨天晚上把已经尘封了3年的mac重新整理了一把,尘封已久的博客也决定重新开始书写,记录一下生活,记录一下成长

  • 显示行号
    set nu

  • 移动光标
    向左移动一个字符 h
    向下移动一个字符 j
    向上移动一个字符 k
    向右移动一个字符 l
    移动至行首 0
    移动至行尾 $
    移动至下一个字的第一个字符 w
    移动至下一个字的最后一个字符 e
    移动至上一个字的第一个字符 b
    移动光标到某一行 :行号

  • 选中 v

  • 复制 y

  • 粘贴 p

  • 删除 d

  • 撤销 u ctrl+r

  • 查找
    /

  • 放弃所有修改并重新载入该文件的原始内容 e!

  • 垂直分割编辑窗口 split

  • 水平分割编辑窗口 vsplit

  • 切换编辑窗口 ctrl + w

linux文件描述符

  • 文件描述符在内核区
  • 进程控制块有文件描述符表,文件描述符号表有1024大小数组,其中0,1,2为默认打开的分别表示标准输入,标准输出,标准错误
  • 每打开一个新文件,则占用一个文件描述符,而且使用的是最小的一个文件描述符

linux虚拟地址空间

  • 0 - 3G为用户区
  • 3G - 4G为内核区
  • ELF是linux下可执行文件的文件格式
  • ELF段 包括.bss(为初始化全局变量) .dada(已经初始化的全局变量) 其他段(只读数据段,符号段) .text(代码段,二进制机器指令)
  • 受保护地址不允许用户访问 #define NULL (void*) 0 在此段
  • 动态库在共享库根据相对地址读取,静态库直接在代码段读取

用户地址空间

栈(stack)

栈又称堆栈,由编译器自动分配释放,行为类似数据结构中的栈(先进后出)。堆栈主要有三个用途:

  • 为函数内部声明的非静态局部变量提供存储空间。
  • 记录函数调用过程相关的维护性信息,称为栈帧(Stack Frame)或过程活动记录(Procedure Activation Record)。它包括函数返回地址,不适合装入寄存器的函数参数及一些寄存器值的保存。除递归调用外,堆栈并非必需。因为编译时可获知局部变量,参数和返回地址所需空间,并将其分配于BSS段。
  • 临时存储区,用于暂存长算术表达式部分计算结果或alloca()函数分配的栈内内存。
内存映射段(mmap)
  • 内核将硬盘文件的内容直接映射到内存, 任何应用程序都可通过Linux的mmap()系统调用或Windows的CreateFileMapping()/MapViewOfFile()请求这种映射。
  • 内存映射是一种方便高效的文件I/O方式, 因而被用于装载动态共享库。用户也可创建匿名内存映射,该映射没有对应的文件, 可用于存放程序数据。在 Linux中,若通过malloc()请求一大块内存,C运行库将创建一个匿名内存映射,而不使用堆内存。
  • 该区域用于映射可执行文件用到的动态链接库。
堆(heap)
  • 堆用于存放进程运行时动态分配的内存段,可动态扩张或缩减。堆中内容是匿名的,不能按名字直接访问,只能通过指针间接访问。
  • 分配的堆内存是经过字节对齐的空间,以适合原子操作。
  • 堆管理器通过链表管理每个申请的内存,由于堆申请和释放是无序的,最终会产生内存碎片。
  • 堆的末端由break指针标识,当堆管理器需要更多内存时,可通过系统调用brk()和sbrk()来移动break指针以扩张堆,一般由系统自动调用。
栈和堆的区别
  1. 管理方式:栈由编译器自动管理;

    堆由程序员控制,易产生内存泄露。
  2. 生长方向:栈向低地址扩展,是连续的内存区域;

    堆向高地址扩展,是不连续的内存区域。这是由于系统用链表来存储空闲内存地址,自然不连续,而链表从低地址向高地址遍历。
  3. 空间大小:栈顶地址和栈的最大容量由系统预先规定(通常默认2M或10M);

    堆的大小则受限于计算机系统中有效的虚拟内存
  4. 存储内容:栈在函数调用时,首先压入主调函数中下条指令(函数调用语句的下条可执行语句)的地址,然后是函数实参,然后是被调函数的局部变量。本次调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的指令地址,程序由该点继续运行下条可执行语句。

    堆通常在头部用一个字节存放其大小,堆用于存储生存期与函数调用无关的数据,具体内容由程序员安排。
  5. 分配方式:栈可静态分配或动态分配。静态分配由编译器完成,如局部变量的分配。动态分配由alloca函数在栈上申请空间,用完后自动释放。

    堆只能动态分配且手工释放。
  6. 分配效率:栈由计算机底层提供支持:分配专门的寄存器存放栈地址,压栈出栈由专门的指令执行,因此效率较高。

    堆由函数库提供,机制复杂,效率比栈低得多。
  7. 分配后系统响应:只要栈剩余空间大于所申请空间,系统将为程序提供内存,否则报告异常提示栈溢出。

    操作系统为堆维护一个记录空闲内存地址的链表。当系统收到程序的内存分配申请时,会遍历该链表寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点空间分配给程序。若无足够大小的空间(可能由于内存碎片太多),有可能调用系统功能去增加程序数据段的内存空间,以便有机会分到足够大小的内存,然后进行返回。,大多数系统会在该内存空间首地址处记录本次分配的内存大小,供后续的释放函数(如free/delete)正确释放本内存空间。此外,由于找到的堆结点大小不一定正好等于申请的大小,系统会自动将多余的部分重新放入空闲链表中。
    1. 碎片问题:栈不会存在碎片问题,因为栈是先进后出的队列,内存块弹出栈之前,在其上面的后进的栈内容已弹出。
      而频繁申请释放操作会造成堆内存空间的不连续,从而造成大量碎片,使程序效率降低。
BSS(Block Started by Symbol)段
  • 未初始化的全局变量和静态局部变量
  • 初始值为0的全局变量和静态局部变量(依赖于编译器实现)
  • 未定义且初值不为0的符号(该初值即common block的大小)
数据段(data)
  • 数据段通常用于存放程序中已初始化且初值不为0的全局变量和静态局部变量。数据段属于静态内存分配(静态存储区),可读可写。

代码段(text)

代码段也称正文段或文本段,通常用于存放程序执行代码

三要素

目标:依赖
命令

自动变量

$< 当前规则中的第一个依赖
$@ 当前规则中的目标
$^ 规则中的所有依赖

函数

获取指定目录下的所有.c文件
src=$(wildcard ./*.c)

.c替换为.o
obj=$(patsubst ./%.o, ./%.c, $(src))

version_1:

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

version_2:

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

main.o:main.c
gcc -c main.c

add.o:add.c
gcc -c add.c

sub.o:sub.c
gcc -c sub.c

mul.o:mul.c
gcc -c mul.c

verson_3:

obj=main.o add.o sub.o mul.o
target=app
CC = gcc
CPPFLAGS = -I
$(target) : $(obj)
$(CC) $(obj) -o $(target)

%.o:%.c
$(CC) -c $< -o $@

version_4:

target=app
CC = gcc
CPPFLAGS = -I
src=$(wildcard ./*.c)
obj=$(patsubst ./%.o, ./%.c, $(src))

$(target) : $(obj)
$(CC) $(obj) -o $(target)

%.o:%.c
$(CC) -c $< -o $@

.PHONY:clean
clean:
rm $(obj) $(target) -f

命令

  • 新创建一个会话
    tmux new -s
  • 查看所有会话
    tmux ls
  • 进入会话
    tmux a(attach) -t
  • 退出会话但不关闭
    tmux detach
  • 退出
    exit

快捷键
ctrl + b 激活控制台
d 退出但不关闭当前会话 相当于 tmux detach
s 切换其他会话

对窗口操作
% 将当前面板分为左右两块
“ 将当前面板分为上下两块
q 显示窗口序号
z 将当前窗口最大化,再按返回
o 切换窗口
方向键 移动光标选择窗口

  1. 启动gdb
    编译 g++ <CODE.cpp> -o -g
    启动gdb gdb
    执行 start/run

  2. 查看代码
    l + :<FUNC|LINE> 默认打开包含吧main函数文件

  3. 设置断点
    设置当前文件的断点
    b(break) + <行号>
    设置指定文件的断点
    b + :<FUNC|LINE>
    设置条件断点
    b(break) + <行号> + 条件

    例: b 22 if i == 1

    删除断点 d + 断点编号

  4. 查看设置的断点
    i(info) + b(break)

  5. 开始执行gdb调试
    开始gdb start
    执行一步操作 n
    执行多步,直到停在断点处 c

  6. 单步调试
    进入函数体内部 s
    从函数体内部跳出 finish
    退出当前循环 u

  7. 查看变量的值
    p + 变量名

  8. 查看变量的类型
    ptype + 变量名

  9. 设置变量的值
    set var 变量名 = 值
    例子 set var i = 10

  10. 设置追踪变量
    display + 变量名

    获取变量编号
    i(info) display

    取消追踪变量
    undisplay + 变量编号

  11. 退出gdb调试
    quit

  12. Linux 命令行规范
    短参数:以单行开头,后跟单一字符,例:ls -h
    长参数:以双横开头,后跟字符串,例:ls –help

    linux 环境变量
    USER 用户名
    HOME 主目录
    PATH 分号分隔的linux查找命令的目录列表

    makefile 负责C/C++ 程序编译与链接
    makefile 文件格式
    target…: prerequisites…
    [Tab] commands

    1. 命令
      history ctrl + p / ctrl + n

      光标移动 字符移动 ctrl + b / ctrl + f

      跳到行首行尾 ctrl + a / ctrl + e
      删除字符 ctrl + h / ctrl + d
      删除所有 ctrl + u
    2. Linux 目录结构

      1. 根目录 /
        /root 超管目录
        /bin binary 存储命令
        /boot 存储启动linux使用的一些核心文件,包括一些链接文件以及镜像文件
        /dev Device 存放linux的外部设备
        /etc 存放所有的系统管理所需要的配置文件子目录
        /home 用户主目录
        /var
        /lib 基本的动态链接共享库
        /lost + found 一般为空,系统非法关机后存放的一些文件
        /usr 用户应用软件资源目录
        /media linux自动识别的一些设备,例如 U盘,光驱等等 自动挂载
        /mnt 系统提供该目录为了让用户临时挂载别的文件系统的 手动挂载

      ~ 宿主文件目录
      $ 普通用户

      超级用户