linux基础 | 青训营笔记

95 阅读8分钟

linux simple command

  • ls可以使用ls+选项+路径

    ls -l -a -h /home
    ls -lah home
    alias ls="ls -ahl --color=auto"	# 使用alias自定义命令
    
  • mkdir创建多层目录-p,和多个目录

    mkdir -p a/b/c
    tree a/	# 递归查看(需要安装)
    mkdir a/ b/ c/
    
  • touch创建文件

    touch a.txt
    touch path/a.txt
    touch -m a.txt	# 更新一下修改时间
    
  • rm删除目录和文件

    rm [-rf] path/a.txt	# r:recursive   f:force
    rm -rf path/folder
    rm *.txt # 删除所有的txt文件
    
  • cp复制文件或文件夹到指定路径

    cp /home/a.txt /home
    cp -r /home /home/folder
    
  • mv(rename)移动和重命名

    mv a.txt b.txt
    mv a.txt /home/a.txt
    
  • man/help获取命令手册(Q退出)

    man ls
    
  • reboot重启和shutdown关机

    reboot
    shutdown -h now	# 立即关闭
    
  • vim简单使用

    vim a.txt
    i -> esc -> :w -> :q(:wq)(:q!)	# i:insert,esc:退出insert,:w:保存改写内容,:q:退出,:q!强制退出
    :set nq # 设置显示行号
    
  • 路径 开头不加/指的是相对路径,加/指的是绝对路径

  • crtl+l清屏

gcc and cmake apt

  1. 安装gcc,gdb

    sudo apt update		# 更新安装软件包来源,安装每个软件前需要执行
    sudo apt install build-essential gdb	#	安装编译器和调试器
    

    检测是否安装成功,查看版本号

    gcc --version
    g++ --version
    gdb --version
    
  2. 安装cmake

    sudo apt install cmake
    cmake --version
    
  3. 安装时可能会遇到一些问题

    # linux下载软件安装包时没有镜像下载慢,若异常退出下载则下次使用缓存会上锁
    sudo rm /var/lib/dpkg/lock-frontend
    sudo rm /var/cache/apt/archives/lock
    sudo rm /var/lib/dpkg/lock
    

GCC编译器编译c/c++

  1. 使用gcc编译c,g++编译c++

  2. 编译过程

    • 预处理pre-processing

      g++ -E a.cpp -o a.i	#	-E对输入文件预处理,生成.i文件
      
    • 编译compiling

      g++ -S a.i -o a.s	# -S指产生汇编文件.s后停止编译
      
    • 汇编assembling

      g++ -c a.s -o a.o	# -c(小写)生成机器语言文件.o
      
    • 链接linking

      g++ a.o -o a	# -o为产生的可执行文件指定文件名(bin文件)
      

​ 整个过程完全等同于g++ a.cpp -o a

  1. g++编译参数

    • -g 编译带调试信息的可执行文件(告诉GCC产生能被GNU调试器GDB使用的调试信息)

      -O[n] 优化源代码,告诉g++对源代码基本优化,缩减代码量,提高可执行文件的运行效率

      • -O/-O1 默认优化,同时减小代码长度和执行时间
      • -O0 不做优化
      • -O2 -O1的基础上进行额外的调整工作如指令调整(一般使用)
      • -O3 包括循环展开和一些其他处理特性相关的优化
      g++ -g a.cpp -o a	# 产生(带调试信息)的可执行文件a,不加则不带调试信息,方便使用GDB调试
      g++ -O2 a.cpp -o a	# 优化源代码输出可执行文件(常用)
      time ./a	# 可看到执行文件的执行时间
      

      [补充]Linux性能分析工具perf

      gcc a.c -g -o a # 用-g使perf可以获取函数信息
      sudo perf record -g ./a sleep 10 # 用perf的record命令记录程序运行情况(生成perf.data文件记录运行数据)
      perf report -g # 用perf的report命令分析程序运行情况
      

      -l和-L -l用来指定程序需要链接的库文件,-l参数后紧跟库名,-L指定库文件目录

      # 若库在/lib和/usr/lib和/usr/local/lib中,用-l
      g++ -gglog a.cpp	# 链接glog库
      # 若不在三个位置,需要用-L指定库文件目录
      g++ -L/path	-ltest a.cpp # 链接path下的test库
      

      -I 指定头文件的目录,/usr/include不需要指定

      g++ -I/path a.cpp # -I也可以依据当前目录使用相对路径
      

      -Wall 打印gcc给出的警告信息(常用)

      -w 关闭警告信息

      g++ -Wall a.cpp # 打印警告
      g++ -w a.cpp # 关闭警告
      

      -std=c++11 设置编译标准(重要)

      g++ -std=c++11 a.cpp # 使用c++11标准编译
      

      -o 指定输出文件名,不加默认为a.out可执行文件(不是文件名的a)

      g++ a.cpp -o a
      

      -D 定义宏

      # 使用gcc/g++编译时定义宏
      # -DDEBUG 定义DEBUG宏,控制文件中DEBUG宏的相关开关
      g++ -DDEBUG a.cpp
      
      #ifdef DEBUG
      	printf("1");
      #endif
          printf("2");
      // 则会执行ifdef
      
  2. g++命令行编译

    • 直接编译运行

      g++ path/main.cpp path1/b.cpp -Ipathinclude -o a # cpp文件和头文件编译为可执行文件,最常用,main和辅助的cpp只需include .h,include:头文件目录,src:源码目录,main:程序入口
      
    • 增加参数编译

      g++ main.cpp b.cpp -std=c++11 -O2 -Wall -o a # 编译标准,优化,打印警告,命名
      
    • 生成库文件并进行编译(静态库会集成到可执行文件中,动态库运行时才会引入)

      • 链接静态库生成可执行文件

        # b.cpp在src下,pathinclude为头文件目录
        g++ b.cpp -c -Ipathinclude # 包含头文件,汇编生成b.o文件[src目录]
        ar rs libb.a b.o # 归档二进制文件生成静态库libb.a[src目录]
        g++ main.cpp -Ipathinclude -Lsrc -lb -o b # 链接生成可执行文件b,头文件地址,库文件目录,库文件,命名
        
      • 链接动态库生成可执行文件

        g++ b.cpp -Ipathinclude -fPIC -shared -o libb.so # 生成动态库文件libb.so,fpic表示与路径无关,shared表示生成动态库文件
        g++ main.cpp -I[pathinclude] -L[src] -l[b] -o b # 链接动态库和头生成可执行文件
        # 生成的可执行文件运行时需要加载.so动态库文件
        LD_LIBRARY_PATH=[src] ./b # 指定.so文件位置,若在同级目录下可不需要
        

GDB调试器

GNU Debugger是用来调试c/c++的调试器,可以用来跟踪程序错误,VS code就是调用GDB实现c/c++调试。需要加-g,回车键可以重复上一指令。

GDB主要功能
设置断点(断点可以是条件表达式),使程序在指定的代码行暂停执行
单步执行程序,查看程序中的变量值的变化
动态改变程序的执行环境
分析崩溃程序产生的core程序
  1. 调试常用命令参数

    gdb [exefile] # 进入GDB调试程序
    gdb help[h] # 查看帮助
    gdb run[r] # 重新开始运行文件run-text:加载文本文件,run-bin:加载二进制文件
    gdb break[b]i # 在第i行设置断点
    gdb start # 单步执行运行程序,并在第一行停止
    gdb list[l] # 查看源代码,list-n:从第n行开始查看代码,list [函数名]查看函数
    gdb set # 设置变量的值
    gdb next[n] # 单步调试,过程(函数跳过)
    gdb step[s] # 单步调试,语句(函数进入)
    gdb info[i] # 查看函数内局部变量的数值
    gdb info breakpints # 查看断点
    gdb finish # 结束当前函数,返回到函数调用点
    gdb continue[c] # 继续执行
    gdb print[p] i # 打印变量i的值及地址,只打印一遍[display]
    gdb quit[q] # 退出GDB
    
  2. 其他调试参数

    gdb backtrace[bt] # 查看函数的调用栈帧和层级关系
    gdb frame[f] # 切换函数的栈帧
    gdb info breakpoints # 查看所有断点
    gdb delete[d] breakpoints i # 删除第i个的断点?行/个
    gdb display # 追踪查看具体变量值,执行中一直打印
    gdb undisplay # 取消追踪观察变量
    gdb watch # 被设置的断点发生修改时,打印提示
    gdb i watch # 显示观察点info watch
    gdb enable breakpoints # 启用断点
    gdb disable breakpoints # 禁用断点
    gdb x # 查看内存x/20xw显示20个单元,16进制,4字节每单元
    gdb run argv[1] argv[2] # 调试时命令行传参
    gdb set follow-fork-mode child # Makefile项目管理,选择跟踪父子进程fork()
    
  3. 使用流程

    # -g编译获得可执行文件a
    gdb a
    run # 运行
    break 13 # 在i行设断点
    info breakpoints # 查看断点
    delete i # 删除第i个断点
    r # 用设置的断点运行,遇到断点会停止
    list # 查看断点周围代码
    print i # 打印变量i的值(一次)
    display i # 一直显示变量i的值
    continue # 继续下次断点
    
    

VS code

  1. 快捷键

    Ctrl+Alt+Shift # linux打开terminal
    
    code . # 用vscode打开当前文件夹
    
    Alt+up/dowm # 将当前代码上移/下移
    Ctrl+Shift+P # 打开code命令面板
    Ctrl+P # 转到文件/其他常用操作
    Ctrl+W # 关闭当前文件
    Ctrl+B # 关闭侧边栏
    Ctrl+`  #打开终端 
    F2 # 变量统一命名
    F12 # 转到定义处
    Ctrl+Shift+N # 打开新窗口
    Ctrl+N # 新建文件
    Ctrl+Tab # 文件切换
    Ctrl+[/] # 代码行缩进
    Ctrl+Enter/[Shift+Enter] # 下插一行,上插一行
    Ctrl+H # 查找替换
    [Fn]+F11 # 全屏
    Ctrl+Shift+I # 格式化代码
    
    CRLF=\r\n # windows下换行
    LF=\n # linux下换行
    

CMake:跨平台的安装编译工具

在工程里额外添加cpp文件时只需添加到cmakelist文件中

  1. 语法特性与常用指令

    # 指令(参数 参数)
    # 指令不分大小写,参数中间用空格或分号,变量使用${}方式取值(IF直接变量名){IF(Var)}
    set(Var a.cpp) # 设置变量Var指代a.cpp
    add_executable(a main.cpp ${Var})=(a main.cpp a.cpp)
    
    • cmake_minimum_required-指定最小版本要求

      cmake_minimum_required(VERSION 2.8.2) # 最低版本要求
      
    • project-命名工程、指定使用语言

      project(a Java) # 工程名为a,使用Java语言
      
    • set-定义变量

      set(Var a.cpp b.cpp) # 定义Var变量
      
    • include_directories-添加头文件路径=[-i]

      link_directories-添加库文件路径=[-L]

      add_library-生成库文件

      include_directories(/path) # 头文件路径
      link_directories(/path /path1) # 链接库文件路径
      add_library(a SHARED/STATIC ${Var}) # 通过变量生成动态/静态库
      
    • add_compile_options-添加编译参数

      add_executable-生成可执行文件

      target_link_libraries-链接动态(shared)库

      add_compile_options(-wall -std=c++ 20 -o2) # 编译参数
      add_executable(a a.cpp) # 生成可执行文件
      add_link_libraries(a a_lib) # 将动态库a_lib连接到可执行文件a上
      
    • add_subdirectory-存放文件目录

      aux_source_directory-将目录下的源代码文件列表存储到变量中

      add_subdirectory(scr) # 添加scr子目录,其中一定要有一个CMakeLists.txt文件
      aux_source_directory(. Var) # 定义Var变量为当前目录下的所有源代码文件
      # 使用场景
      add_executable(main ${Var}) # 生成main可执行文件
      
    • 常用变量

      CMAKE_C_FLAGS-gcc编译选项

      CMAKE_CXX_FLAGS-g++编译选项

      CAMKE_BUILD_TYPE-编译类型

      CMAKE_C/CXX_COMPILER-指定c编译器

      EXECUTABLE_OUTPUT_PATH-可执行文件的输出存放路径

      LIBRARY_OUTPUT_PATH-库文件输出存放路径

      set(CMAKE_CXX_FLAGS "${CAMKE_CXX_FLAGS} -std=c++20") # g++编译选项后追加-std=c++20
      set(CMAKE_BUILD_TYPE Debug) # 变异类型Debug,调试时选择debug
      set(CMAKE_BUILD_TYPE Release) # 变异类型Release,发布时选择release
      
  2. Cmake编译工程

    • 目录结构(顶层目录有CMakeLists.txt文件)编译规则

      1. 源文件同级目录(子)有CMakeLists.txt文件,顶层目录的CMakeLists.txt通过add_subdirectory将子目录添加进来。
      2. 源文件同级目录(子)无CMakeList.txt文件,子目录的编译规则体现在顶层目录的CMakeLists.txt中。
    • 流程

      1. 手动编写CMakeLists.txt,cmake指令
      2. 执行cmake PATH命令生成Makefile,PATH为txt所在目录(. ./为当前目录,.. ../为上级目录)
      3. 执行make命令编译
    • 构建方式

      1. 内部构建:直接读当前目录的CMakeLists.txt,产生很多中间文件,

        cmake . # 当前目录编译CmakeLists.txt生成makefile等中间文件
        make # make命令编译
        
      2. 外部构建(推荐):在新目录下读上级目录的CMakeLists.txt,中间文件保存在新目录下。

        # 创建并进入新目录
        mkdir newbulid
        cd newbulid 
        # 编译
        cmake .. # 编译上级目录中的CMakeList.txt,生成makefile和其他文件在newbuild中
        make
        
    • 编译示例

      CMakeLists.txt(vs code中需要设置cmake tool的设置cmake路径才能会自动填充)
      
      # 指定最小版本要求
      cmake_minimum_required(VERSION 3.0)
      # 指定项目名称
      project(hello_test)
      # 添加头文件路径
      include_directories(include) # -I头文件路径
      # 存放文件目录,源文件目录存入变量DIR_SRC中
      add_subdirectory(src DIR_SRC)
      # 生成可执行文件exe
      add_executable(exe main.cpp src/a.cpp)
      
      ==g++ main.cpp src/a.cpp -Iiclude -o2 exe
      
      内部构建(文件杂乱)
      cmake . # 编译CMakeLists.txt生成makefile
      make # 生成可执行文件,add_executabe中指定的名称
      
      外部构建
      mkdir build
      cd build
      cmake ..
      make
      
      

综合设计

  1. 调试配置

    • launch.json

      "program" : 调试的可执行程序路径(${workspaceFolder}/)

      "preLaunchTask" : 调试前预处理指令

    • tasks.json

      "label" : 任务名

      "command" : 命令

      "dependsOn"

  2. 目录设计

    include:存储头文件,头文件要有#pragma once,函数定义

    src:源文件,函数实现

    build:编译构建文件

    ${CMAKE_SOURCE_DIR} :顶级目录路径

    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall ") 	# 追加编译选项 
    set(CMAKE_BUILD_TYPE Debug) # 生成可调试的文件