Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions docs/dev/library.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
---
icon: simple/cplusplus
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

换个图标,和 C/C++ 的重复了

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

material/book 或者 material/book-cog 不错,material/bookmark-box 也行

---

# 链接库
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

主标题名称需与 nav 里面一致。


!!! note "主要作者"

[@luojh][luojh]

!!! warning "本文编写中"

!!! comment "适用范围"

本文介绍 Linux 上的**静态链接库** (一般为 `.a` 文件) 和**动态链接库** (一般为 `.so` 文件)。注意:这里的链接库是指包含了可执行二进制代码的库,并不是头文件 (Header file)、Python 库等。
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

括号内包含中文的情况下使用全角括号,下面其他的也一样。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Header file 不需要大写,header file 就够了


## 总览

库 (Library),是包含**可重用代码和数据**的模块。

### 构建链接库

下图给出了一般的可执行文件 (executable)、静态链接库 (static library)、动态链接库 (dynamic library) 的构建过程。

```mermaid
flowchart TD

source["源文件 (*.c, *.cpp)"] -->|编译| target["目标文件 (*.o)"]
header["头文件 (*.h)"] --- source
target -->|链接| executable["可执行文件 (ELF等)"]
target -->|ar rcs| staticlib["静态链接库 (*.a)"]
target -->|gcc -shared| dynamiclib["动态链接库 (*.so)"]
```

### 使用链接库

下图给出了**使用链接库**的方式。

```mermaid
flowchart TD
source["源文件 (*.c, *.cpp)"] -->|编译| target["目标文件 (*.o)"]
header["头文件 (*.h)"] --- source
target --> linker["链接器"]
staticlib["**静态链接库** (链接步骤加入)"] --> linker
linker --> executable["可执行文件 (ELF等)"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
linker --> executable["可执行文件 (ELF等)"]
linker --> executable["可执行文件(ELF 等)"]

dynamiclib["**动态链接库** (运行时加载)"] --> executable
```

## 源代码

对于 C 程序而言,链接库的源代码就是普通函数、变量之类,并无太多特殊要求。例如,创建并进入目录 `lib`,在 `square.c` 源文件中写一个函数 `square`:

```c
int square(int x)
{
return x * x;
}
```

对应的,需要在头文件 `square.h` 中加入这个函数的原型 (prototype):

```c
int square(int x);
```

以便其他使用链接库的程序**知道如何使用这个函数** (即使这些程序不知道函数内部的实现)。
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

有必要讲一下预处理。


因为链接库不是完整的、可以独立运行的程序,因此不需要入口点 (比如 `main` 函数)。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

介绍一下 extern

## 静态链接库

静态链接库是在**链接步骤就加入**的链接库类型。

### 构建

首先按照正常方法编译得到 `.o` 文件:

```shell
gcc square.c -c -o square.o
```

然后使用 `ar` 程序创建静态链接库 `libsquare.a`:

```shell
ar rcs libsquare.a square.o
```

注意这里的 `libsquare.a` 是命名惯例:一般静态链接库的文件名需要为 `lib<名称>.a`。

到这里就完成了静态链接库的创建。

### 使用

另一个 C 程序 `main.c` 中使用了 `square` 函数,那么首先需要包含 `square.h` 头文件,这样才能知道这个函数的原型,然后就可以正常调用了。

```c
#include <stdio.h>
#include "lib/square.h"

int main(void)
{
int a;
scanf("%d", &a);

printf("%d^2 = %d\n", a, square(a));
return 0;
}
```

下面的命令可以将这个程序直接编译 - 链接到可执行文件 `main` (也可以分开成单独的编译步骤、链接步骤)。

```shell
gcc main.c -L./lib -lsquare -o main
```

这里,`-L./lib` 表示要求链接器在 `./lib` 中寻找链接库,`-lsquare` 表示需要链接 `libsquare.a` 这个静态链接库文件。

编译好之后,就可以正常使用了。由于静态链接库中的代码会被直接合并到链接产生的可执行文件 `main` 中,因此运行时不需要文件 `libsquare.a`。
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

frankly 读到这里结束我稍微有点意外,更期待一点 in-depth 的内容……

目前这个内容量大概可以作为 101 的拓展内容……?如果介绍一些 LD_LIBRARY_PATH(例如不同 CUDA 版本等)/打包相关的也许更适合放在 201 一些。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

现在这个分量确实是不够的


## 动态链接库

动态链接库与静态链接库类似,都是首先需要对库的代码进行编译。但是,动态链接库需要生成位置无关代码 (PIC),且是在依赖这个库的程序**运行时**由加载器 (loader) 动态加载到内存空间中的。

!!! comment "关于动态加载"

如果多个程序共用一份动态链接库,那么内存中可以只有一份动态链接库的二进制代码,所有程序通过虚拟内存机制“看到”这份二进制代码,而非像静态链接库那样每个依赖于它的程序中都嵌入一份,有效节约了空间。

也正因为此,动态库和依赖于动态库的程序是分开存储的 (两个不同的文件),这可能会带来一些问题:

- 不同版本的动态库可能都安装在系统上,如果使用了不正确的版本,库提供的接口可能不对应,这会导致栈不平衡等严重的问题。
- 动态链接库 (特别是常用的那些) 有被恶意修改的可能,如果程序依赖一个动态库而它被修改的话,几乎可以执行任意代码。
1 change: 1 addition & 0 deletions includes/authors.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@
[zeyugao]: https://github.com/zeyugao
[relic-yuexi]: https://github.com/relic-yuexi
[Jerry-Kwan]: https://github.com/Jerry-Kwan
[luojh]: https://github.com/luojh
35 changes: 18 additions & 17 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -138,21 +138,22 @@ nav:
- Grafana: ops/monitor/grafana.md
- 安全: ops/security.md
- 开发速查手册:
- dev/index.md
- 编程语言概览:
- dev/language/index.md
- 前端简介: dev/language/frontend.md
- Python: dev/language/python.md
- C/C++ 与构建工具: dev/language/cxx.md
- Shell 脚本: dev/language/shell.md
- Golang: dev/language/golang.md
- 版本管理与合作: dev/git.md
- SSH 使用技巧: dev/ssh.md
- dev/index.md
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不要修改这个文件的 indentation

- 编程语言概览:
- dev/language/index.md
- 前端简介: dev/language/frontend.md
- Python: dev/language/python.md
- C/C++ 与构建工具: dev/language/cxx.md
- Shell 脚本: dev/language/shell.md
- Golang: dev/language/golang.md
- 版本管理与合作: dev/git.md
- SSH 使用技巧: dev/ssh.md
- Linux 上的链接库: dev/library.md
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

层级需在「编程语言概览」下面,预期是在 cxx.md 里面。现在的内容量没法单列一个 page。

- 高级内容:
- advanced/index.md
- CUDA 环境简介: advanced/cuda.md
- Linux 桌面与窗口系统: advanced/desktop.md
- DAC 与 MAC: advanced/dac-mac.md
- Caddy: advanced/caddy.md
- Nmap: advanced/nmap.md
- ELK: advanced/elk.md
- advanced/index.md
- CUDA 环境简介: advanced/cuda.md
- Linux 桌面与窗口系统: advanced/desktop.md
- DAC 与 MAC: advanced/dac-mac.md
- Caddy: advanced/caddy.md
- Nmap: advanced/nmap.md
- ELK: advanced/elk.md