Aix上使用库文件和编写库文件。

2024-03-04 00:08
文章标签 使用 编写 aix

本文主要是介绍Aix上使用库文件和编写库文件。,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Aix上使用库文件和编写库文件。
一直以来,被动态链接库,静态库,静态链接,动态链接,最近又听到运行时链接弄得一塌糊涂。天下文章一大抄,知道的大家都知道,静态链接是编译时链接,生成的文件大,动态链接是运行时链接,生成的文件小。不知道的大家都不知道,或者大家都以为自己知道...有时windows,有时linux,有时Aix,有时gcc,有时g++,有时cc,有时xlc,有时.so,有时.a,有时.dll有时.lib有时.o,太多不一致,太多麻烦。
还有,因为工作的原因,经常在以Aix为工作环境,有的说.so是动态链接库,.a是静态链接库,但在Aix上咋看咋不像。
这周末,我花了两天时间研究Aix上的这些问题,用的是vac的xlc和ccs的ld,不能说现在有多了解,但至少不像以前那么糊涂了。现在做做总结。

一,链接文件和链接方式。
其实没有将动态链接和动态链接方式仔细地想一想,是导致我原来混乱的主要原因。之所以想到这个问题,是在工作中要编写一个库a,那我要编译a,然后要写另一个库b,b依赖于a,我又要编译b,在这个过程中,我开始思考,我当初编译a的时候是用的什么链接方式,我现在要用a了,那a又是什么?
于是我开始区分链接文件和链接方式,开始了以下实验
1,使用库文件libc.a,静态链接成可执行程序
hello.c

C代码
#include <stdio.h>    
int main() {    
  printf("Hello, world!\n");    
}   
#include <stdio.h>
int main() {
printf("Hello, world!\n");
}


运行
# xlc  -o hello.o -c hello.c
生成目标文件hello.o
运行
ld -o hello_s -bstatic hello.o -lc
想静态链接hello.o和libc.a,并生成可执行文件hello_s。我这里没有直接使用xlc来生成可执行文件,是想把其中每一步弄清楚,结果求知的代价就是大量的时间和无尽的搜索。-bnso是告诉ld静态链接。(你还可以用xlc的-E和-S参数看hello.c的预处理文件和汇编文件,再用as来编译汇编文件生成对象文件)
结果
ld: 0711-327 WARNING: Entry point not found: __start
ld: 0711-244 ERROR: No csects or exported symbols have been saved.
这里说没有找到__start,这个__start看起来很像系统的一个子历程。出现这个错的原因是因为我们没有在链接时加入这样一个库/usr/lib/crt0.o,如果你用xlc直接静态链接,那么这个库应该是xlc自己帮你加的(这个库好像是线程初始化相关),你可以通过nm命令查看这个目标文件相关的symbol,里面是包含有__start的。于是我们再运行
ld -o hello_s -bstatic hello.o -lc /usr/lib/crt0.o
结果报错说一大堆符号找不到,
ld: 0711-224 WARNING: Duplicate symbol: .is_posix_tz
ld: 0711-224 WARNING: Duplicate symbol: .__icuinit
ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information.
ld: 0711-317 ERROR: Undefined symbol: __loadx
ld: 0711-317 ERROR: Undefined symbol: _system_TB_config
ld: 0711-317 ERROR: Undefined symbol: errno
ld: 0711-317 ERROR: Undefined symbol: .___bzero
ld: 0711-317 ERROR: Undefined symbol: smcr_timebase
ld: 0711-317 ERROR: Undefined symbol: .___memmove
ld: 0711-317 ERROR: Undefined symbol: .___memset
ld: 0711-317 ERROR: Undefined symbol: _system_configuration
ld: 0711-317 ERROR: Undefined symbol: disclaim
ld: 0711-317 ERROR: Undefined symbol: kwritev
ld: 0711-317 ERROR: Undefined symbol: kpwritev
ld: 0711-317 ERROR: Undefined symbol: kpwrite
ld: 0711-317 ERROR: Undefined symbol: kwrite
ld: 0711-317 ERROR: Undefined symbol: kopenx
...
ld提示可以用-bloadmap来查看具体的出错信息,于是我运行
ld -o hello_s -bstatic hello.o -lc /usr/lib/crt0.o -bloadmap:out.txt
并查看输出文件,得到
...
ld: 0711-318 ERROR: Undefined symbols were found.
        The following symbols are in error:
 Symbol                    Inpndx  TY CL Source-File(Object-File) OR Import-File{Shared-object}
                              RLD: Address  Section  Rld-type Referencing Symbol
 ----------------------------------------------------------------------------------------------
 __loadx                   [262]   ER DS (/usr/lib/libc.a[shr.o])
                                   0006919c .data    R_POS    [1658]  <__loadx>
 _system_TB_config         [792]   ER UA (/usr/lib/libc.a[shr.o])
                                   000691a8 .data    R_POS    [1664]  <_system_TB_config>
 errno                     [8]     ER UA (/usr/lib/libc.a[shr.o])
                                   00068e3c .data    R_POS    [1226]   
...
这说明是libc.a中的shr.o中的定义的一些符号找不到,于是我们将这个shr.o解出来,运行
ar -x /usr/lib/libc.a shr.o
得到shr.o,然后
ldd shr.o
得到输出
shr.o needs:
         /unix
         /usr/lib/libcrypt.a(shr.o)
         /usr/lib/libc.a(shr.o)
这个shr.o需要以上三个库,libc.a我们已经包括了,那么哪里去找/unix这个库?相比现在所找不到的符号应该都是系统调用吧。查看ld的手册得知我们需要导入系统调用的符号表/lib/syscalls.exp
于是我们再运行
# ld -o hello_s -bstatic hello.o -lc /usr/lib/crt0.o -bI:/lib/syscalls.exp
结果还是报错
# ld -o hello_s -bstatic hello.o -lc /usr/lib/crt0.o -bI:/lib/syscalls.exp
ld: 0711-224 WARNING: Duplicate symbol: .open
ld: 0711-224 WARNING: Duplicate symbol: .openx
ld: 0711-224 WARNING: Duplicate symbol: .is_posix_tz
ld: 0711-224 WARNING: Duplicate symbol: .__icuinit
ld: 0711-224 WARNING: Duplicate symbol: .send
ld: 0711-224 WARNING: Duplicate symbol: .nrecvmsg
ld: 0711-224 WARNING: Duplicate symbol: .nrecvfrom
ld: 0711-224 WARNING: Duplicate symbol: .recvmsg
ld: 0711-224 WARNING: Duplicate symbol: .recvfrom
ld: 0711-224 WARNING: Duplicate symbol: .recv
ld: 0711-224 WARNING: Duplicate symbol: .nsendmsg
ld: 0711-224 WARNING: Duplicate symbol: .sendmsg
ld: 0711-224 WARNING: Duplicate symbol: .sendto
ld: 0711-224 WARNING: Duplicate symbol: .naccept
ld: 0711-224 WARNING: Duplicate symbol: .accept
ld: 0711-224 WARNING: Duplicate symbol: .thread_wait
ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information.
ld: 0711-317 ERROR: Undefined symbol: encrypted_pw_passlen
ld: 0711-317 ERROR: Undefined symbol: crypt_r
ld: 0711-317 ERROR: Undefined symbol: max_history_size
ld: 0711-317 ERROR: Undefined symbol: getpass_auto
ld: 0711-317 ERROR: Undefined symbol: max_pw_passlen

但现在只有少量符号找不到了,我查看/lib下还有哪些exp,但是没有发现和加密解密相关,我又查看/lib/syscalls.exp的内容,发现里面也只是一些符号表,我怀疑是否可以自己创建一个符号表。结果网上的一篇资料证实了我的想法,于是我创建一个名为StaticLinkScript的文件,输入:
#!
encrypted_pw_passlen
crypt_r
max_history_size
getpass_auto
max_pw_passlen
接着运行:
# ld -o hello_s -bstatic hello.o -lc /usr/lib/crt0.o -bI:/lib/syscalls.exp -bI:StaticLinkScript
虽然有些警告,但是hello_s还是生出来了。运行
# ./hello_s
Hello, world!成功出现,然后再运行
# ls -l
看到这个文件近3M,仅仅一个printf语句,可以估计这个是静态链接出来的文件了
-rw-r--r--    1 root     system           78 Nov 30 04:41 StaticLinkScript
-rw-r--r--    1 root     system         1812 Dec 02 07:52 crt0.syms
-rw-r--r--    1 root     system           64 Nov 29 09:39 hello.c
-rw-r--r--    1 root     system         1100 Dec 02 07:28 hello.o
-rwxr-xr-x    1 root     system      2963741 Dec 02 08:28 hello_s
-rw-r--r--    1 root     system        36438 Dec 02 08:00 out.txt
-r-xr-xr-x    1 root     system      5111233 Dec 02 08:03 shr.o
-rw-r--r--    1 root     system       657423 Nov 30 03:41 shr.syms
在运行
ldd hello_s
结果
hello_s needs:
         /unix
这充分证明hello_s是静态出链接出来的。好了,有了上面的经历,后面就简单了

2,使用库文件libc.a,动态链接成可执行程序
我们去掉-bstatic选项,运行
# ld -o hello_d hello.o -lc /usr/lib/crt0.o -bI:/lib/syscalls.exp -bI:StaticLinkScript
生成可以成功运行的可执行文件hello_d,我们再 运行
# ldd hello_d
输出
hello_d needs:
         /usr/lib/libc.a(shr.o)
         /unix
         /usr/lib/libcrypt.a(shr.o)
这说明hello_d是动态链接出来的。或者运行
# ls -l
得到
-rwxr-xr-x    1 root     system         4402 Dec 02 08:37 hello_d
-rwxr-xr-x    1 root     system      2963741 Dec 02 08:28 hello_s


这里我们得到一个结论,Aix上其实没有动态链接库和静态链接库的概念,只有共享对象的概念: shared object,即so,拿到一个.so,你可以将它静态链接到某个可执行程序上去,也可将它静态链接到某个可执行程序上去。

3,关于-bstatic选项和-nso选项
手册上说,它只将它之后的共享对象以静态链接的方式链接起来,所以,我们来看看以下结果
# ld -o hello_s -bstatic hello.o -lc /usr/lib/crt0.o -bI:/lib/syscalls.exp -bI:StaticLinkScript
# ld -o hello_s2 -lc -bstatic hello.o /usr/lib/crt0.o -bI:/lib/syscalls.exp -bI:StaticLinkScript
# ld -o hello_s3 hello.o -bstatic -lc /usr/lib/crt0.o -bI:/lib/syscalls.exp -bI:StaticLinkScript
# ld -o hello_s4 -lc -bnso hello.o /usr/lib/crt0.o -bI:/lib/syscalls.exp -bI:StaticLinkScript
# ls -l
-rwxr-xr-x    1 root     system         4402 Dec 02 08:37 hello_d
-rwxr-xr-x    1 root     system      2963741 Dec 02 08:28 hello_s
-rwxr-xr-x    1 root     system         4402 Dec 02 08:38 hello_s2
-rwxr-xr-x    1 root     system      2963741 Dec 02 08:39 hello_s3
-rwxr-xr-x    1 root     system      2963741 Dec 02 09:13 hello_s4

这验证了-bstatic并不是让所有共享对象以静态方式链接。同样,我们知道了.so和.o文件的区别,.so可以动态或静态链接到结果,而.o好像只能静态链接到结果,或者说.o根本就不是共享文件,不能用上动态链接的概念,只能说被链接,那么这里的链接就只能是将.o文件的静态链接了
另外,以上例子说明-bnso选项是对全局有效的。

4,编写“静态链接库”,和使用“静态链接库”
按照我们第3步的分析,所谓的静态链接库可以认为就是.o文件,aix上又可以把文件打包成.a文件。难怪有人会说.a就是静态链接库
我们先写源文件mylib.h和mylib.c
mylib.h

C代码
void hello();    
mylib.c    
#include <stdio.h>    
int m1 = 1;    
char m2[10];    
char *m3 = "jjww";    
   
void hello(){    
  int i = 0;    
  char name[10];    
  name[0] = 'l';    
  name[1] = 'i';    
  name[2] = 'u';    
  name[3] = '\0';    
   
  printf("success call from perl to c library: i=%d, name=%s, m3=%s\n", i, name, m3);    
}   
void hello();
mylib.c
#include <stdio.h>
int m1 = 1;
char m2[10];
char *m3 = "jjww";
void hello(){
int i = 0;
char name[10];
name[0] = 'l';
name[1] = 'i';
name[2] = 'u';
name[3] = '\0';
printf("success call from perl to c library: i=%d, name=%s, m3=%s\n", i, name, m3);
}


运行
# xlc -o mylib.o -c mylib.c
得到mylib.o,打包成mylib.a,运行
ar -r mylib.a mylib.o
好了,所谓的“静态链接库”就出来了
编写应用程序test_lib.c

C代码
#include "mylib.h"    
int main() {    
  hello();    
}   
#include "mylib.h"
int main() {
hello();
}


运行
# xlc -o test_lib.o -c test_lib.c
得到对象文件test_lib.o
运行
# ld -o test_lib_s test_lib.o mylib.o -bnso /usr/lib/crt0.o -lc -bI:/lib/syscalls.exp -bI:StaticLinkScript
# ld -o test_lib_s2 test_lib.o mylib.a -bnso /usr/lib/crt0.o -lc -bI:/lib/syscalls.exp -bI:StaticLinkScript
# ld -o test_lib_d test_lib.o mylib.o /usr/lib/crt0.o -lc -bI:/lib/syscalls.exp -bI:StaticLinkScript
# ld -o test_lib_d2 test_lib.o mylib.a /usr/lib/crt0.o -lc -bI:/lib/syscalls.exp -bI:StaticLinkScript
# mv mylib.a libmylib.a
# ld -o test_lib_s3 test_lib.o -L"." -lmylib /usr/lib/crt0.o -lc -bI:/lib/syscalls.exp -bI:StaticLinkScript
# ls -l  
得到
-rwxr-xr-x    1 root     system         4868 Dec 02 09:22 test_lib_d
-rwxr-xr-x    1 root     system         4868 Dec 02 09:22 test_lib_d2
-rwxr-xr-x    1 root     system      2964203 Dec 02 09:19 test_lib_s
-rwxr-xr-x    1 root     system      2964203 Dec 02 09:19 test_lib_s2
-rwxr-xr-x    1 root     system         4870 Dec 02 09:28 test_lib_s3
前两个语句我是静态链接成可执行程序,接下来的两个采用动态链接,最后一个,我仿照libc.a生成了一个libmylib.a,想动态链接mylib.a,但是发现test_lib_s3比test_lib_d和test_lib_d2略大,而且
# ldd test_lib_s3
得到
test_lib_s3 needs:
         /usr/lib/libc.a(shr.o)
         /unix
         /usr/lib/libcrypt.a(shr.o)
依赖列表中没有/libmylib.a,可以说明/libmylib.a还是被静态链接的,就和其他的test_lib.o一样

5,编写共享对象.so,和使用.so
# xlc -o libmylib.so  -qmkshrobj mylib.c
# xlc -o libmylib2.so -qmkshrobj -c mylib.c
生成共享对象libmylib.so,注意前者没有-c而后者有,libmylib2.so被生成为一般的oject文件,虽然其后缀是.so,比如
# ldd libmylib.so
输出
libmylib.so needs:
         /usr/lib/libc.a(shr.o)
         /unix
         /usr/lib/libcrypt.a(shr.o)
# ldd libmylib2.so
输出
libmylib2.so needs:
除了大小和mylib.o一样外,libmylib2.so同样不依赖任何库
运行
# ld -o test_lib_ss  -lc libmylib.so test_lib.o -bnso /usr/lib/crt0.o -bI:/lib/syscalls.exp -bI:StaticLinkScript
# ld -o test_lib_dd  -lc libmylib.so test_lib.o /usr/lib/crt0.o -bI:/lib/syscalls.exp -bI:StaticLinkScript
# ld -o test_lib_dd2 -lc -L"." libmylib.so test_lib.o /usr/lib/crt0.o -bI:/lib/syscalls.exp -bI:StaticLinkScript
# ldd test_lib_dd
test_lib_dd needs:
         /usr/lib/libc.a(shr.o)
Cannot find libmylib.so
         /unix
         /usr/lib/libcrypt.a(shr.o)
# ldd test_lib_dd2
test_lib_dd2 needs:
         /usr/lib/libc.a(shr.o)
         ./libmylib.so
         /unix
         /usr/lib/libcrypt.a(shr.o)
test_lib_dd虽然成功生成,但是文件有问题,从ldd test_lib_dd2的结果看出,/libmylib.so是被动态链接了 。


这篇关于Aix上使用库文件和编写库文件。的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/771372

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

git使用的说明总结

Git使用说明 下载安装(下载地址) macOS: Git - Downloading macOS Windows: Git - Downloading Windows Linux/Unix: Git (git-scm.com) 创建新仓库 本地创建新仓库:创建新文件夹,进入文件夹目录,执行指令 git init ,用以创建新的git 克隆仓库 执行指令用以创建一个本地仓库的

【北交大信息所AI-Max2】使用方法

BJTU信息所集群AI_MAX2使用方法 使用的前提是预约到相应的算力卡,拥有登录权限的账号密码,一般为导师组共用一个。 有浏览器、ssh工具就可以。 1.新建集群Terminal 浏览器登陆10.126.62.75 (如果是1集群把75改成66) 交互式开发 执行器选Terminal 密码随便设一个(需记住) 工作空间:私有数据、全部文件 加速器选GeForce_RTX_2080_Ti

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念