Linux 环境 C++ 编程
C++ 环境准备
sudo apt-get install g++ 安装编译器。sudo apt-get install gdb 安装调试器。
在 vscode 中安装拓展
编译指令
简单:”g++ 选项 源文件名”,例如 g++ -o test main.cpp
高级:”g++ 选项 源文件名 输出选项 链接库”,例如 g++ -std=c++17 -Wall -O2 -I./include main.cpp -o my_app -L./lib -lpthread
编译选项
-std=c++17指定 C++ 标准。-I./include指定头文件搜索路径。-g调试,Wall警告。-On编译、链接时优化,提高可执行程序运行速度,减慢编译速度,默认-O0, 推荐-O2。-c只编译不链接,常用于把源文件编译成静态库或动态库。输出选项
-o 文件名指定输出文件名。链接库
-L./libs指定库文件搜索路径。-l库文件名链接库,若库文件名为libpthread.so则命令为-lpthread。
静态库和动态库
若动态库和静态库同时存在,编译器将优先使用动态库。
概念与特点
静态库:程序在编译时把库文件的二进制代码链接到目标程序中,这种方式称为静态链接。
如果多个程序中用到了同一静态库中的函数或类,就会存在多份拷贝。
- 静态库的链接在编译时期完成,执行时代码加载速度快。
- 目标程序的可执行文件较大,浪费空间。
- 程序的更新和发布不方便,一个静态库更新后,所有使用它的程序都需要重新编译。
动态库:程序在运行时把库文件的二进制代码载入。
如果多个进程中用到了同一动态库中的函数或类,内存中只会存在一份,避免了空间浪费问题
- 可实现进程间的代码共享,因此动态库也称为共享库。
- 程序升级较简单,无需重新编译程序,只需更新动态库即可。
- 需要提前设置
LD_LIBRARY_PATH环境变量。
制作
制作静态库
1.”g++ -c 源代码文件清单”,如g++ -c source1.cpp source2.cpp source3.cpp
2.”ar rcs lib库名.a 目标文件清单”,如ar rcs libmylib.a source1.o source2.o source3.o制作动态库
“g++ -fPIC -shared 源代码文件清单 -o lib库名.so”,如g++ -fPIC -shared math.cpp -o libmymath.so
Makefile 与 CMake
Makefile
- 在目录下创建文件 “Makefile” ,编写命令内容。开头需要使用
Tab缩进,而非空格。 - 运行命令
make即可编译链接出可执行程序,使用 “./程序名” 运行。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38# # v1
# test: main.cpp printhello.cpp factorial.cpp
# g++ -o test main.cpp printhello.cpp factorial.cpp
# # v2
# CXX = g++
# TARGET = test
# OBJ = main.o printhello.o factorial.o
# # make 时执行 g++, 先找 TARGET , TARGET 不存在找 OBJ, OBJ 不存在,编译三个 .cpp 文件生成 .o 文件
# # 然后再链接 OBJ 文件,生成可执行文件 hello
# $(TARGET): $(OBJ)
# $(CXX) -o $(TARGET) $(OBJ)
# # 编译 OBJ
# main.o: main.cpp
# $(CXX) -c main.cpp
# printhello.o: printhello.cpp
# $(CXX) -c printhello.cpp
# factorial.o: factorial.cpp
# $(CXX) -c factorial.cpp
# v3
CXX = g++
TARGET = hello
OBJ = main.o printhello.o factorial.o
# 编译选项,显示所有的warning
CXXFLAGS = -c -Wall
# $@表示的就是冒号前面的TARGET,$^表示的是冒号后OBJ的全部.o依赖文件
$(TARGET): $(OBJ)
$(CXX) -o $@ $^
# $<表示指向%.cpp依赖的第一个,但是这里依赖只有一个
# $@表示指向%.o
%.o: %.cpp
$(CXX) $(CXXFLAGS) $< -o $@
# 为了防止文件夹中存在一个文件叫clean
# -f表示强制删除,此处表示删除所有的.o文件和TARGET文件
clean:
rm -f *.o $(TARGET)
CMake
- 在项目根目录下创建 .txt文件
CMakeLists.txt,编写内容。1
2
3
4
5
6
7
8
9
10
11
12
13cmake_minimum_required(VERSION 3.10)
project(test)
set(CMAKE_CXX_STANDARD 20) # 指定 C++ 标准
add_executable(test main.cpp factorial.cpp printhello.cpp)
## 自动查找当前目录下所有的源文件,并将列表赋值给变量 SRC_LIST
#aux_source_directory(. SRC_LIST)
## 使用变量 SRC_LIST 编译程序,不用手写 main.cpp factorial.cpp ...
#add_executable(test ${SRC_LIST}) - 创建 “build” 文件夹
mkdir build,进入该目录cd build。 - 运行命令
cmake ..,执行根目录的内容,在当前目录生成 “Makefile”。 - 运行命令
make即可编译链接出可执行程序,使用 “./程序名” 运行。
GDB 调试
待写
Linux 的系统错误
strerror() 函数在 <cstring> 中,用于获取错误代码对应的详细信息。
错误原因保存在全局变量 errno 中,值只有在库函数调用发生错误时才会被设置,当库函数调用成功时,errno 的值不会被修改,不会主动的置为0。
1 |
|
Linux 的信号
Linux 的文件 IO
<unistd.h>open() 首个文件返回值为3,012已被文件描述符占用, close() 关闭,成功返回0失败-1。int fd = open("a.txt", ...); 等于把文件描述符分配给 fd
O_RDONLY: 只读的方式打开O_WRONLY:只写的方式打开O_RDWR: 读写的方式打开O_CREATE: 如果文件不存在,就创建文件O_APPEND: 以追加的方式打开文件read()读,成功返回实际读到的字节数,读到结束返回0,失败返回-1write()写,成功返回写入字节数,失败返回-1lseek()控制指针位置。
其他
grep 逐行扫描,并匹配的行打印出来| 管道,ps -ef | grep nginx 查找并列出系统当前运行的 nginx 进程
Linux 的时间操作
Linux 的目录操作
access() 函数用于判断当前用户对目录或文件的存取权限。
stat 结构体
struct stat 结构体用于存放目录或文件的详细信息,成员变量比较多,重点关注 st_mode, st_size 和 st_mtime 成员。
注意:st_mtime 是一个整数表示的时间,需要程序员自己写代码转换格式。st_mode 成员的取值很多,用以下两个宏来判断:S_ISREG(st_mode) 是否为普通文件,如果是,返回真。S_ISDIR(st_mode) 是否为目录,如果是,返回真。
1 | struct stat |
stat() 库函数
1 | // stat() 函数获取 path 参数指定目录或文件的详细信息,保存到 buf 结构体中。 |
rename() 函数用于重命名目录或文件,相当于操作系统的 mv 命令。remove() 函数用于删除目录或文件,相当于操作系统的 rm 命令。
