Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
编程进阶之路
计算机科学
提交
5cb8c3fa
计
计算机科学
项目概览
编程进阶之路
/
计算机科学
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
计
计算机科学
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
5cb8c3fa
编写于
9月 12, 2023
作者:
编程进阶之路
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
符号版本化
上级
726abf58
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
159 addition
and
2 deletion
+159
-2
assets/Linux-UNIX系统编程手册(上下册合集)_1694420599654_0.edn
assets/Linux-UNIX系统编程手册(上下册合集)_1694420599654_0.edn
+1
-1
code/USP/SharedLibraries/version_script/symbolic_version/sv_lib_v1.c
...aredLibraries/version_script/symbolic_version/sv_lib_v1.c
+7
-0
code/USP/SharedLibraries/version_script/symbolic_version/sv_lib_v2.c
...aredLibraries/version_script/symbolic_version/sv_lib_v2.c
+16
-0
code/USP/SharedLibraries/version_script/symbolic_version/sv_prog.c
...SharedLibraries/version_script/symbolic_version/sv_prog.c
+7
-0
code/USP/SharedLibraries/version_script/symbolic_version/sv_v1.map
...SharedLibraries/version_script/symbolic_version/sv_v1.map
+6
-0
code/USP/SharedLibraries/version_script/symbolic_version/sv_v2.map
...SharedLibraries/version_script/symbolic_version/sv_v2.map
+11
-0
pages/USP-共享库高级特性.md
pages/USP-共享库高级特性.md
+111
-1
未找到文件。
assets/Linux-UNIX系统编程手册(上下册合集)_1694420599654_0.edn
浏览文件 @
5cb8c3fa
...
...
@@ -70,4 +70,4 @@
:page
736
}
,
:content
{
:text
"[:span]"
,
:image
1694437268292
}
,
:properties
{
:color
"purple"
}}]
,
:extra
{
:page
75
5
}}
:extra
{
:page
75
7
}}
code/USP/SharedLibraries/version_script/symbolic_version/sv_lib_v1.c
0 → 100644
浏览文件 @
5cb8c3fa
#include <stdio.h>
void
xyz
(
void
)
{
printf
(
"v1 xyz
\n
"
);
}
code/USP/SharedLibraries/version_script/symbolic_version/sv_lib_v2.c
0 → 100644
浏览文件 @
5cb8c3fa
#include <stdio.h>
__asm__
(
".symver xyz_old,xyz@VER_1"
);
__asm__
(
".symver xyz_new,xyz@@VER_2"
);
void
xyz_old
(
void
)
{
printf
(
"v1 xyz
\n
"
);
}
void
xyz_new
(
void
)
{
printf
(
"v2 xyz
\n
"
);
}
void
pqr
(
void
)
{
printf
(
"v2 pqr
\n
"
);
}
code/USP/SharedLibraries/version_script/symbolic_version/sv_prog.c
0 → 100644
浏览文件 @
5cb8c3fa
#include <stdlib.h>
int
main
(
int
argc
,
char
*
argv
[])
{
void
xyz
(
void
);
xyz
();
exit
(
EXIT_SUCCESS
);
}
\ No newline at end of file
code/USP/SharedLibraries/version_script/symbolic_version/sv_v1.map
0 → 100644
浏览文件 @
5cb8c3fa
VER_1 {
global:
xyz;
local:
*;
};
\ No newline at end of file
code/USP/SharedLibraries/version_script/symbolic_version/sv_v2.map
0 → 100644
浏览文件 @
5cb8c3fa
VER_1 {
global:
xyz;
local:
*;
};
VER_2 {
global:
pqr;
} VER_1;
pages/USP-共享库高级特性.md
浏览文件 @
5cb8c3fa
...
...
@@ -227,8 +227,117 @@
```
-
可以看出
`vis_comm()`
不再对外可见了
-
## 符号版本化
collapsed:: true
-
符号版本化允许一个共享库提供同一个函数的多个版本。每个程序会使用它与共享库进行(静态)链接时函数的当前版本。这种处理方式的结果是可以对共享库进行不兼容的改动而无需提升库的主要版本号。从极端的角度来讲,符号版本化可以取代传统的共享库主要和次要版本化模型。glibc 从 2.1 开始使用了这种符号版本化技术,因此 glibc 2.0 以及之前的所有版本都是通过单个主要库版本(
`libc.so.6`
)来支持的
-
下面通过一个简单的例子来展示符号版本化的用途。首先使用一个版本脚本来创建共享库的第一个版本
-
-
在一个
`sv_lib_v1.c`
文件键入
-
```c
#include <stdio.h>
void xyz(void) {
printf("v1 xyz\n");
}
```
-
在
`sv_v1.map`
中键入
-
```c
VER_1 {
global: xyz;
local: *;
};
```
-
为了使例子尽量简单点,这里没有使用显式的库 soname 和库主要版本号
-
```shell
[dyp@dyp symbolic_version]$ gcc -g -c -fPIC -Wall sv_lib_v1.c
[dyp@dyp symbolic_version]$ gcc -g -shared -o libsv.so sv_lib_v1.o -Wl,--version-script,sv_v1.map
```
-
在这个阶段,版本脚本
`sv_v1.map`
只用来控制共享库的符号的可见性,即只导出
`xyz()`
,同时隐藏其他所有符号(在这个简短的例子中没有其他符号了)。接着创建一个程序
`p1`
来使用这个库
id:: 65001349-5ac5-439f-93f2-64ea09bcb0e7
-
```c
#include <stdlib.h>
int main(int argc, char *argv[]) {
void xyz(void);
xyz();
exit(EXIT_SUCCESS);
}
```
-
```shell
[dyp@dyp symbolic_version]$ gcc -g -o p1 sv_prog.c libsv.so
[dyp@dyp symbolic_version]$ ./p1
./p1: error while loading shared libraries: libsv.so: cannot open shared object file: No such file or directory
[dyp@dyp symbolic_version]$ LD_LIBRARY_PATH=. ./p1
v1 xyz
```
-
现在假设需要修改库中
`xyz()`
的定义,但同时仍然需要确保程序
`pl`
继续使用老版本的函数。为完成这个任务,必须要在库中定义两个版本的
`xyz()`
。我们在
`sv_lib_v2.c`
中键入
-
```c
#include <stdio.h>
__asm__(".symver xyz_old,xyz@VER_1");
__asm__(".symver xyz_new,xyz@@VER_2");
void xyz_old(void) {
printf("v1 xyz\n");
}
void xyz_new(void) {
printf("v2 xyz\n");
}
void pqr(void) {
printf("v2 pqr\n");
}
```
-
这里两个版本的
`xyz()`
是通过函数
`xyz_old()`
和
`xyz_new()`
来实现的
-
`xyz_old()`
函数对应于原来的
`xyz()`
定义,
`p1`
程序应该继续使用这个函数
-
`xyz_new()`
函数提供了与库的新版本进行链接的程序所使用的
` xyz()`
的定义
-
修改过的版本脚本(稍后给出)中的两个
`.symver`
汇编器指令将这两个函数绑定到了两个不同的版本标签上,下面将使用这个脚本来创建共享库的新版本。第一个指令指示与版本标签
`VER_1`
进行链接的应用程序(即程序
`p1`
)所使用的
`xyz()`
的实现是
`xyz_old()`
,与版本标签
`VER_2`
进行链接的应用程序所使用的
`xyz()`
的实现是
`xyz_new()`
-
第二个
`.symver`
指令使用
`@@`
(不是
`@`
)来指示当应用程序与这个共享库进行静态链接时应该使用的
`xyz()`
的默认定义。一个符号的
`.symver`
指令中应该只有一个指令使用
`@@`
标记
-
下面是与修改过之后的库对应的版本脚本
-
```
VER_1 {
global:
xyz;
local:
*;
};
VER_2 {
global:
pqr;
} VER_1; # 标记依赖 VER_1
```
-
这个版本脚本提供了一个新版本标签
`VER_2`
,它依赖于标签
` VER_1`
。这种依赖关系是通过
`} VER_1;`
进行标记的
-
现在按照以往方式构建库的新版本
-
```shell
[dyp@dyp symbolic_version]$ gcc -g -c -fPIC -Wall sv_lib_v2.c
[dyp@dyp symbolic_version]$ gcc -g -shared -o libsv.so sv_lib_v2.o -Wl,--version-script,sv_v2.map
```
-
现在创建一个新程序
` p2`
,它使用了
`xyz()`
的新定义,同时程序
`p1`
使用了旧版的
`xyz()`
-
```shell
[dyp@dyp symbolic_version]$ gcc -g -o p2 sv_prog.c libsv.so
[dyp@dyp symbolic_version]$ LD_LIBRARY_PATH=. ./p2
v2 xyz
[dyp@dyp symbolic_version]$ LD_LIBRARY_PATH=. ./p1
v1 xyz
```
-
[[$green]]==可执行文件的版本标签依赖是在静态链接时进行记录的==。使用
`objdump –t`
可以打印出每个可执行文件的符号表,从而能够显示出两个程序中不同的版本标签依赖
-
```shell
[dyp@dyp symbolic_version]$ objdump -t p1 | grep xyz
0000000000000000 F *UND* 0000000000000000 xyz@VER_1
[dyp@dyp symbolic_version]$ objdump -t p2 | grep xyz
0000000000000000 F *UND* 0000000000000000 xyz@VER_2
```
-
## 初始化和终止函数
-
[[#green]]==可以定义一个或多个在
**共享库被加载和卸载时自动执行**
的函数,这样在使用共享库时就能够完成一些初始化和终止工作了==。不管库是自动被加载还是使用
`dlopen`
接口显式加载的,初始化函数和终止函数都会被执行
-
初始化和终止函数是使用
`gcc`
的
`constructor`
和
`destructor`
特性来定义的
-
在库被加载时需要执行的所有函数都应该定义成下面的形式
-
```c
```
-
-
-
-
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录