WebServer04

我们先学习一下epoll:

select/poll/epoll - 知乎

接下来调整一下学习策略。这么多行代码,一行行去读、搞懂每个api如何调用也不现实,而且只读代码对能力的提升还是不如动手实操。接下来打算自己实现一个简单的回声服务器,接着融入多线程、I/O多路复用,理解了之后再回头看WebServer

许久没有打开项目了,中途配置cs144的lab环境,出现了一点问题:VSCode竟然不认识如cassert等库,连std都不认识了!写了一个简单的测试代码,虽然VSCode报错,但是可以正常编译并运行。看起来是VSCode的问题。

先禁用官方的C/C++扩展,使用clangd. 由于项目有makefile,所以直接用bear工具(生成编译数据库)

sudo apt update
sudo apt install bear
cd ~/项目
​
#清理旧编译文件
make clean
​
bear -- make #用bear生成compile_commands.json文件

Ctrl+Shift+P,找到Clangd:Restart Language Server,点击

但还是不行。我们检查一下compile_commands.json:

[
  {
    "arguments": [
      "/usr/bin/g++",
      "-c",
      "-g",
      "-o",
      "server",
      "main.cpp"
    ],
    "directory": "/home/kevin/cpp-projects/TinyWebServer",
    "file": "/home/kevin/cpp-projects/TinyWebServer/main.cpp",
    "output": "/home/kevin/cpp-projects/TinyWebServer/server"
  },
  {
    "arguments": [
      "/usr/bin/g++",
      "-c",
      "-g",
      "-o",
      "server",
      "timer/lst_timer.cpp"
    ],
    "directory": "/home/kevin/cpp-projects/TinyWebServer",
    "file": "/home/kevin/cpp-projects/TinyWebServer/timer/lst_timer.cpp",
    "output": "/home/kevin/cpp-projects/TinyWebServer/server"
  },
  {
    "arguments": [
      "/usr/bin/g++",
      "-c",
      "-g",
      "-o",
      "server",
      "http/http_conn.cpp"
    ],
    "directory": "/home/kevin/cpp-projects/TinyWebServer",
    "file": "/home/kevin/cpp-projects/TinyWebServer/http/http_conn.cpp",
    "output": "/home/kevin/cpp-projects/TinyWebServer/server"
  },
  {
    "arguments": [
      "/usr/bin/g++",
      "-c",
      "-g",
      "-o",
      "server",
      "log/log.cpp"
    ],
    "directory": "/home/kevin/cpp-projects/TinyWebServer",
    "file": "/home/kevin/cpp-projects/TinyWebServer/log/log.cpp",
    "output": "/home/kevin/cpp-projects/TinyWebServer/server"
  },
  {
    "arguments": [
      "/usr/bin/g++",
      "-c",
      "-g",
      "-o",
      "server",
      "CGImysql/sql_connection_pool.cpp"
    ],
    "directory": "/home/kevin/cpp-projects/TinyWebServer",
    "file": "/home/kevin/cpp-projects/TinyWebServer/CGImysql/sql_connection_pool.cpp",
    "output": "/home/kevin/cpp-projects/TinyWebServer/server"
  },
  {
    "arguments": [
      "/usr/bin/g++",
      "-c",
      "-g",
      "-o",
      "server",
      "webserver.cpp"
    ],
    "directory": "/home/kevin/cpp-projects/TinyWebServer",
    "file": "/home/kevin/cpp-projects/TinyWebServer/webserver.cpp",
    "output": "/home/kevin/cpp-projects/TinyWebServer/server"
  },
  {
    "arguments": [
      "/usr/bin/g++",
      "-c",
      "-g",
      "-o",
      "server",
      "config.cpp"
    ],
    "directory": "/home/kevin/cpp-projects/TinyWebServer",
    "file": "/home/kevin/cpp-projects/TinyWebServer/config.cpp",
    "output": "/home/kevin/cpp-projects/TinyWebServer/server"
  }
]

可以看到在文件中我们没有指定C++标准,也没有包含系统标准库头文件路径

更改如下:(JSON是不能有注释的,这里只是为了说明)

[
  {
    "arguments": [
      "/usr/bin/g++",
      "-c",
      "-g",
      "-std=c++11",  //添加C++11标准
      "-I/usr/include/c++/11",  //系统标准库路径
      "-I/usr/include/x86_64-linux-gnu/c++/11",  //架构相关标准库路径
      "-I/usr/include",  //系统默认头文件路径
      "-o",
      "server",
      "main.cpp"
    ],
    "directory": "/home/kevin/cpp-projects/TinyWebServer",
    "file": "/home/kevin/cpp-projects/TinyWebServer/main.cpp",
    "output": "/home/kevin/cpp-projects/TinyWebServer/server"
  },
  {
    "arguments": [
      "/usr/bin/g++",
      "-c",
      "-g",
      "-std=c++11",
      "-I/usr/include/c++/11",
      "-I/usr/include/x86_64-linux-gnu/c++/11",
      "-I/usr/include",
      "-o",
      "server",
      "timer/lst_timer.cpp"
    ],
    "directory": "/home/kevin/cpp-projects/TinyWebServer",
    "file": "/home/kevin/cpp-projects/TinyWebServer/timer/lst_timer.cpp",
    "output": "/home/kevin/cpp-projects/TinyWebServer/server"
  },
  {
    "arguments": [
      "/usr/bin/g++",
      "-c",
      "-g",
      "-std=c++11",
      "-I/usr/include/c++/11",
      "-I/usr/include/x86_64-linux-gnu/c++/11",
      "-I/usr/include",
      "-o",
      "server",
      "http/http_conn.cpp"
    ],
    "directory": "/home/kevin/cpp-projects/TinyWebServer",
    "file": "/home/kevin/cpp-projects/TinyWebServer/http/http_conn.cpp",
    "output": "/home/kevin/cpp-projects/TinyWebServer/server"
  },
  {
    "arguments": [
      "/usr/bin/g++",
      "-c",
      "-g",
      "-std=c++11",
      "-I/usr/include/c++/11",
      "-I/usr/include/x86_64-linux-gnu/c++/11",
      "-I/usr/include",
      "-o",
      "server",
      "log/log.cpp"
    ],
    "directory": "/home/kevin/cpp-projects/TinyWebServer",
    "file": "/home/kevin/cpp-projects/TinyWebServer/log/log.cpp",
    "output": "/home/kevin/cpp-projects/TinyWebServer/server"
  },
  {
    "arguments": [
      "/usr/bin/g++",
      "-c",
      "-g",
      "-std=c++11",
      "-I/usr/include/c++/11",
      "-I/usr/include/x86_64-linux-gnu/c++/11",
      "-I/usr/include",
      "-o",
      "server",
      "CGImysql/sql_connection_pool.cpp"
    ],
    "directory": "/home/kevin/cpp-projects/TinyWebServer",
    "file": "/home/kevin/cpp-projects/TinyWebServer/CGImysql/sql_connection_pool.cpp",
    "output": "/home/kevin/cpp-projects/TinyWebServer/server"
  },
  {
    "arguments": [
      "/usr/bin/g++",
      "-c",
      "-g",
      "-std=c++11",
      "-I/usr/include/c++/11",
      "-I/usr/include/x86_64-linux-gnu/c++/11",
      "-I/usr/include",
      "-o",
      "server",
      "webserver.cpp"
    ],
    "directory": "/home/kevin/cpp-projects/TinyWebServer",
    "file": "/home/kevin/cpp-projects/TinyWebServer/webserver.cpp",
    "output": "/home/kevin/cpp-projects/TinyWebServer/server"
  },
  {
    "arguments": [
      "/usr/bin/g++",
      "-c",
      "-g",
      "-std=c++11",
      "-I/usr/include/c++/11",
      "-I/usr/include/x86_64-linux-gnu/c++/11",
      "-I/usr/include",
      "-o",
      "server",
      "config.cpp"
    ],
    "directory": "/home/kevin/cpp-projects/TinyWebServer",
    "file": "/home/kevin/cpp-projects/TinyWebServer/config.cpp",
    "output": "/home/kevin/cpp-projects/TinyWebServer/server"
  }
]

-std=c++11告诉clangd用c++11标准解析代码

-I明确告诉clangd系统标准库头文件的位置

在其它项目中是否需要构建这个compile_commands.json文件?需要,因为clangd的功能完全依赖它提供的编译上下文。如果项目用的是MakeFile,那么通常使用bear工具,就和前文一样:

make clean
bear -- make

对于更大型的项目,一般都是使用CMake

所以CMake和MakeFile究竟是什么?它们都是构建工具,核心作用是帮我们自动化管理C/C++项目的编译流程。例如一个项目有100个文件,你每次修改都要编译100个文件太麻烦了。而且不同的人可能使用不同的编译选项。构建工具解决的就是这几个问题:自动化、增量编译(只编译修改的文件)、统一配置。

makefile:

#1.定义变量:编译选项、目标文件名、源文件
CXX = g++                #用g++编译
CXXFLAGS = -std=c++11 -Wall  #编译选项:C++11 标准、开启警告
TARGET = myapp           #最终生成的可执行文件名
SRC = main.cpp tool.cpp  #所有源文件
​
#2.生成目标文件
$(TARGET): $(SRC)        #myapp依赖于 main.cpp 和 tool.cpp
    $(CXX) $(CXXFLAGS) $(SRC) -o $(TARGET)  #实际执行的编译命令(注意开头必须是Tab缩进)
​
# 3.清理编译产物
clean:
    rm -f $(TARGET) *.o  #执行make clean时,删除可执行文件和中间文件
make        #自动执行编译命令,生成myapp
make clean  #清理编译产物(重新编译前用)

可见Makefile是比较简单的,实际上就是写命令+定义依赖。如果我们只修改了main.cpp,那么它只会编译main.cpp,再和tool.o链接。但是它的缺点也比较明显:需要手写规则(新增一个.cpp文件就要添加到SRC变量中),此外Windows系统下需要MinGW等工具支持。

而CMake则是更加高级的构建工具。它不直接编译代码,而是帮你自动生成Makefile(或者VisualStudio工程、XCode工程等)。CMake允许我们用跨平台的语法写一个CMakeLists.txt(必须要是这个名字),然后自动生成对应平台的构建文件。它的核心优势在于:跨平台(同一个CMakeLists.txt,在Linux生成Makefile,在Mac OS生成XCode工程,在Windows生成VisualStudio工程)、简化配置(自动找源文件、自动处理依赖)、支持复杂项目(处理多目录、动态/静态库、第三方依赖)

补充说一下动态库和静态库:

比喻:你发现你的一道错题涉及某个定理。静态库就是你把这个定理抄在题目旁边,动态库就是你在旁边批注“见课本第80页定理”。前者:你写的会多一点,但你看试卷复习的时候就不需要翻阅课本了。后者:你写的少一点,但看试卷复习的时候就需要课本了。

先回忆 C/C++ 程序的编译流程:源代码(.cpp)-> 编译(生成 .o 目标文件 -> 链接(合并 .o 文件+库文件)-> 可执行文件

静态库和动态库的核心区别在链接阶段:

静态库后缀名:Linux 下是 .a(archive),Windows 下是 .lib

链接过程:编译器会把静态库中你用到的代码段、函数直接复制到你的 .o 文件中,最终合并成一个独立的可执行文件

运行时:可执行文件不依赖任何外部库,直接运行,因为需要的代码都在自己体内

例:你用静态库 liblog.a(日志工具包),链接后生成 webserver 可执行文件 ——webserver 里已经包含了日志功能的代码,即使删除 liblog.awebserver 依然能正常打印日志。

动态库后缀名:Linux 下是 .so(shared object),Windows 下是 .dll(dynamic link library)

链接过程:编译器不会复制库的代码,只会在你的可执行文件中记录 “我需要用到 xxx 动态库的 xxx 函数”,相当于留了一个引用地址

运行时:可执行文件启动后,系统会先查找对应的动态库(比如 /usr/lib/liblog.so),加载到内存中,然后通过引用地址调用库中的函数。如果找不到动态库,程序会直接报错退出,比如 Linux 下的 error while loading shared libraries: liblog.so: cannot open shared object file

例:你用动态库 liblog.so,链接后生成 webserver——webserver 体积很小,但运行时必须依赖 liblog.so 存在于系统中;如果 liblog.so 被更新,比如修复了一个 bug,你不用重新编译 webserver,下次运行时会自动使用新的库

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值