Linux服务器项目-1
牛客网Linux高性能服务器项目学习总结:
资料下载:C++课件和代码_免费高速下载|百度网盘-分享无限制 (baidu.com)
0.1 前言
对于想在C++领域求职的人来说,Linux服务器部分基本是必须要掌握的内容,这部分涉及到的内容比较广,包括网络编程,计算机网络,Linux内核等方面的内容。我们可能都学过这些课程,但是想要将学过的知识融会贯通,形成一套体系,并且能够做项目还是有一定难度的,这也是本课程的意义所在。
1.1 开发环境
首先需要配置本次课程涉及到的开发环境,包括linux环境,VScode,Xshell,Xftp等。其中linux环境安装在虚拟机中,在虚拟机中的linux系统上安装ssh server后,就可以通过电脑主机通过Xshell连接电脑主机进行命令行操作了。
此外,也可以通过VScode配合插件查看linux中的程序,并通过命令行进行调试了。
1.2 GCC
GCC(GNU Compile Collection)是一个编译器套件,可以编译C,C++,Java等语言,也包括了这些语言的库。
GCC可以通过命令行控制编译器遵循那个标准翻译源代码,比如-std=c99就是C99标准。
安装:sudo apt-get install gcc g++
gcc对应C语言,g++对应C++语言
查看版本:gcc/g++ -v/--version
编译指令:生成app.o
文件gcc test.c -o app
,在执行./app
即可得到程序结果。或者直接gcc test.c
,生成一个a.out
文件
GCC工作流程:源代码首先经过预处理,将.h,.c,.cpp文件放入放入主文件中,删除注释,宏替换等生成预处理后源代码.i文件,在经过编译器生成汇编代码.s文件,最后经过汇编器生成目标代码.o文件,结合启动代码,库代码和其他目标代码经过链接器工具进行链接,生成可执行文件,(windows中是.exe,linux中是.out)。
gcc编译选项 | 说明 |
---|---|
-E | 预处理指定的源文件,不进行编译 |
-S | 编译指定的源文件,但是不进行汇编 |
-c(s) | 编译、汇编指定的源文件,但是不进行链接 |
-o [file1] [file2] /[file2] o [file1] | 将文件file2 编译成可执行文件 file1 |
-I directory(大写i) | 指定include 包含文件的搜索目录 |
-g | 在编译的时候,生成调试信息,该程序可以被调试器调试 |
-D | 在程序编译的时候,指定一个宏,后面跟着的就是宏名字的参数,方便我们进行程序调试 |
-w | 不生成任何警告信息 |
-Wall | 生成所有警告信息 |
-On | n的取值范围: 0~3 。编译器的优化选项的 4 个级别, O0 表示没有优化, O1 为缺省值, O3 优化级别最高 |
-l(小写L) | 在程序编译的时候,指定使用的库 |
-L | 指定编译的时候,搜索的库的路径。 |
-fPIC fpic | 生成与位置无关的代码 |
-shared | 生成共享目标文件,通常用在建立共享库时 |
-std | 指定C 方言,如 std=c99 gcc 默认的方言是 GNU C |
几个误区:
误区一:
gcc
只能编译c
代码,g++
只能编译c++
后缀为
.c
的,gcc
把它当作是C
程序,而g++
当作是c++
程序后缀为
.cpp
的,两者都会认为是C++
程序,C++
的语法规则更加严谨一些编译阶段,
g++
会调用gcc
,对于C++
代码,两者是等价的,但是因为gcc
命令不能自动和C++
程序使用的库联接,所以通常用g++
来完成链接,为了统一起见,干脆编译 链接统统用g++
了,这就给人一种错觉,好像cpp
程序只能用g++
似的误区二:
gcc
不会定义__cplusplus
宏,而g++
会实际上,这个宏只是标志着编译器将会把代码按
C
还是C++
语法来解释如上所述,如果后缀为
.c
,并且采用gcc
编译器,则该宏就是未定义的,否则,就是已定义误区三:编译只能用
gcc
,链接只能用g++
严格来说,这句话不算错误,但是它混淆了概念,应该这样说:编译可以用
gcc/g++ g++
,而链接可以用g++
或者gcc lstdc++
。gcc
命令不能自动和C++
程序使用的库联接,所以通常使用g++
来完成联接。但在编译阶段,
g++
会自动调用gcc
,二者等价
1.3 静态库和动态库
概述:
- 库是计算机上的一类文件,可以将其看作一种仓库代码。提供一些可以直接用的变量,函数或类。
- 库是也是一种程序,但是其不能单独运行。
- 库文件包括动态库和静态库(共享库)两种。但是静态库在程序链接阶段被复制到了程序中;动态库链接时没有复制到程序中,而是在程序运行时由系统动态加载到内存中供程序调用。
- 库的好处:1. 代码保密 2.方便部署和分发
静态库的命名规则:
- Linux: libxxx.a;其中lib为固定的前缀,xxx为自己起的库的名字,.a为自己定的后缀。
- Windows:libxxx.lib
静态库的制作:
使用
gcc - c
生成.o
文件将
.o
文件打包,==使用ar工具(archive)==:1
2r - 将文件插入备存文件中 c - 建立备存文件 s - 索引
ar rcs libxxx.a xxx.o xxx.o
静态库的使用:
拷贝文件:
cp -r calc/ library/ ../lesson05
删除所有的
.o
文件:rm *.o
一般代码项目的目录结构为,
include
包含项目用到的所有头文件;lib
包含项目用到的库函数;src
为项目用到的源文件。使用时要将库函数和其用到的头文件分发给用户,否则是无法使用的。
具体方法:
1 | -I是头文件位置,-l是库的名称,-L是库的路径 |
动态库的命名规则:
- Linux: libxxx.so;其中lib为固定的前缀,xxx为自己起的库的名字,.so为固定的后缀。在linux下是可执行文件
- Windows:libxxx.dll
动态库的制作:
gcc得到.o文件,得到和位置无关的代码
1
gcc -c -fpic/-fPIC a.c b.c
gcc得到动态库
1
gcc -shared a.o b.o -o libcalc.so
然后执行:
1 | -I是头文件位置,-l是库的名称,-L是库的路径 |
但是会报错:error while loading shared libraries:
这是由于静态库和动态库的工作原理不同。
静态库: GCC 进行链接时,会把静态库中代码打包到可执行程序中
动态库: GCC 进行链接时,动态库的代码不会被打包到可执行程序中
程序启动之后,动态库会被动态加载到内存中,通过 ldd list dynamic
dependencies )命令检查动态库依赖关系
当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径。此时就需要系统的动态载入器来获取该绝对路径。径。此时就需要系统的动态载入器来获取该绝对路径。对于 elf 格式的可执行程序,是由 ld linux.so
来完成的。即/lib64/ld-linux-x86-64.so.2 (0x00007f0b16c16000)
它先后搜索 elf
文件的 DT_RPATH
段 —> 环境变量LD_LIBRARY_PATH
—> /etc/ld.so.cache
文件列表 —> / lib/
,/usr/lib
目录找到库文件后将其载入内存。
配置到环境变量中的具体方法:
1 | 配置临时环境变量,这种方法只有本次shell中可用 |
静态库和动态库的对比
程序编译成可执行文件的过程
库比较小使用静态库,库比较大使用动态库。
静态库的优缺点:
优点:
静态库被打包到应用程序中加载速度快
发布程序无需提供静态库,移植方便
缺点:
- 消耗系统资源,浪费内存
- 更新、部署、发布麻烦
动态库的优缺点:
优点:
- 可以实现进程间资源共享(共享库)
- 更新、部署、发布简单
- 可以控制何时加载动态库
缺点:
- 加载速度比静态库慢
- 发布程序时需要提供依赖的动态库
动态库和静态库的对比:
静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库,因此体积较大。
动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在,因此代码体积较小