轻松学会Linux下查看SO接口函数方法 (linux查看so接口函数)

在Linux下开发应用程序时,我们经常会使用动态链接库(.so文件)来共享代码,提高程序的执行效率。SO接口函数是动态链接库中公开的函数,开发人员可以调用这些函数实现特定的功能。但是,有时候我们需要查看这些SO接口函数的定义,以便更好地理解和使用它们。本文将介绍Linux下查看SO接口函数的方法,相信读完后你就可以轻松掌握这个技能了。

一、使用nm命令查看SO库函数

nm命令是Linux下的一个二进制程序查看工具,用于查看可执行文件和共享对象(即.so文件)中的符号表。nm命令有三个常用的选项:-A、-a和-D,它们分别表示对所有符号、对所有符号和调试符号以及对所有动态符号表符号进行列出。以下是使用nm命令查看SO库函数的详细步骤:

1. 打开终端,进入SO库所在的目录

2. 输入以下命令,列出这个SO库中的所有符号及其地址:

nm -gC .so

其中,-g表示显示全局符号,-C表示显示C++符号

3. 查找你要查看的函数名,如果该函数被定义在SO库中,就会在列表中出现,其地址就是函数名前面的十六进制数值

4. 接下来可以查看该函数的定义,使用objdump命令,输入以下命令:

objdump -D .so | grep 函数名

其中,-D表示反汇编所有节(section)的内容,然后使用grep命令过滤出包含该函数名的内容。

二、使用readelf命令查看SO库函数

readelf是一个Linux系统下的ELF格式可执行文件的查看工具。ELF(Executable and Linkable Format)是Linux下二进制文件格式的标准,它包含了代码、数据和符号表等多种信息。下面是使用readelf命令查看SO库函数的方法:

1. 打开终端,进入SO库所在的目录

2. 输入以下命令,查看SO库中的符号表:

readelf -s .so

其中,-s表示显示符号表

3. 查找你要查看的函数名,如果该函数被定义在SO库中,它就会在列表中出现,其地址就是第三列的十六进制数值

4. 接下来可以查看该函数的定义,使用objdump命令,输入以下命令:

objdump -D .so | grep 函数名

其中,-D表示反汇编所有节(section)的内容,然后使用grep命令过滤出包含该函数名的内容。

三、使用nm、readelf和objdump联合使用查看SO库函数

以上两种方法都可以查看SO库中的符号表及函数地址,但是只能通过objdump命令查看函数的定义。如果想要更直接地查看函数的定义,那么可以将这三个命令联合使用。以下是具体步骤:

1. 打开终端,进入SO库所在的目录

2. 输入以下命令,查看符号表:

nm -D .so | grep 函数名

其中,-D表示显示动态符号表,grep命令用于过滤出包含该函数名的条目。这个命令会显示出函数的地址和符号名。

3. 接下来使用以下命令,查看函数的定义:

objdump -D .so | grep -A20 -B20 函数名

其中,-A20表示显示函数名后面20行对象的内容,-B20表示显示函数名前面20行的内容。这样就可以直接查看函数的定义了。

以上就是在Linux下查看SO接口函数的方法,希望对你有所帮助。不过需要注意的是,这种查看方法只适用于开发人员,在日常使用中更好不要动SO文件、静态库文件、可执行文件等,否则可能会导致系统崩溃。

相关问题拓展阅读:

请教关于android linux动态库.so的加载调用

1、 .so动态库的生成

可使用gcc或者g++编译器生成动态库文件(此处以g++编译器为例)

g++ -shared -fPIC -c XXX.cpp

g++ -shared -fPIC -o XXX.so XXX.o

2、 .so动态库的动态调用接口函数说明

动态库的调用关系可以在需要调用动态库的程序编译时,通过g++的-L和-l命令来指定。例如:程序test启动时需要加载目录/root/src/lib中的libtest_so1.so动态库,编译命令可照如下编写执行:

g++ -g -o test test.cpp –L/root/src/lib –ltest_so1

(此处,我们重点讲解动态库的动态调用的方法,关于静态的通过g++编译命令调用的方式不作详细讲解,具体相关内容可上网查询)

Linux下,提供专门的一组API用于完成打开动态库慧芦,查找符号,处理出错,关闭动态库等功能。

下面对这些接口函数逐一介绍(调用这些接口时,需引用头文件#include ):

1)dlopen

函数原型:void *dlopen(const char *libname,int flag);

功能描述:dlopen必须在dlerror,dlsym和dlclose之前调用,表示要将库装载到内存,准备使用。如果要装载的库依赖于其它库,必须首先装载依赖库。如果dlopen操作失败,返回NULL值;如果库已经被装载过,则dlopen会返回同样的句柄。

参数中的libname一般是库的全路径,这样dlopen会直接装载该文件;如果只是指定了库名称,在dlopen会按照下面的机制去搜寻:

a.根据环境变量LD_LIBRARY_PATH查找

b.根据/etc/ld.so.cache查找

c.查找依次在/lib和/usr/lib目录查找。

flag参数表示处理未定义函数的方式,可以使用RTLD_LAZY或RTLD_NOW。RTLD_LAZY表示暂时不去处理未定义函数,迅搜先把库装载到内存,等用到没定义的函数再说;RTLD_NOW表示马上检查是否存在未定义的函数,若存在,则dlopen以失败告终。

2)dlerror

函数原型:char *dlerror(void);

功能描述:dlerror可以获得最近一次dlopen,dlsym或dlclose操作的错误信息,返回NULL表示无错误。dlerror在返回错误信息的同时,也会清除错误信息。

3)dlsym

函数原型:void *dlsym(void *handle,const char *symbol);

功能描述:在dlopen之后,库被装载到内存。dlsym可以获得指定函数(symbol)在内前昌带存中的位置(指针)。如果找不到指定函数,则dlsym会返回NULL值。但判断函数是否存在更好的方法是使用dlerror函数,

4)dlclose

函数原型:int dlclose(void *);

功能描述:将已经装载的库句柄减一,如果句柄减至零,则该库会被卸载。如果存在析构函数,则在dlclose之后,析构函数会被调用。

3、 普通函数的调用

此处以源码实例说明。各源码文件关系如下:

test_so1.h和test_so1.cpp生成test_so1.so动态库。

test_so2.h和test_so2.cpp生成test_so2.so动态库。

test_dl.cpp生成test_dl可执行程序,test_dl通过dlopen系列等API函数,并使用函数指针以到达动态调用不同so库中test函数的目的。

请问我有一个.so文件,如何在Linux下编程使用呢?

Linux下的.so是基于linux下的动态链接,其功能和作用类似与windows下.dll文件。

下面是关于.so的介绍:

一、引言

通常情况下,对函数库的链接是放在编译时期(compile time)完成的。所有相关的对象文件(object file)与牵涉到的函数库(library)被链接合成一个可执行文件(executable file)。程序在运行时,与函数库再无瓜葛,因为所有需要的函数已拷贝到自己门下。所以这些函数库被成为静态库(static libaray),通常文件名为“lib.a”的形式。

其实,我们也可以把对一些库函数的链接载入推迟到程序运行的时期(runtime)。这就是如雷贯耳的动态链接库(dynamic link library)技术。

二、动态链接库的特点与优势

首先让我们来看一下,把库函数推迟到程序运行时期载入的好处:

1. 可以实现进程之间的资源共享。

什么概念呢?就是说,某个程序的在运行中要调用某个动态链接库函数的时候,操作系统首先会查看所有正在运行的程序,看在内存里是否已有此库函数的拷贝了。如果有,则让其共享那一个拷贝;只有没有才链接载入。这样的模式虽然会带来一些“动态链接”额外的开销,却大大的节省了系统的内存资源。C的标准库就是动态链接库,也就是说系统中所有运行的程序共享着同一个C标准库的代码段。

2. 将一些程序升级变得简单。用户只需要升级动态链接库,而无需重新编译链接其他原有的代码就可以完成整个程序的升级。Windows 就是一个很好的例子。

3. 甚至可以真正坐到链接载入完全由程序员在程序代码中控制。

程序员在编写程序的时候,可以明确的指明什么时候或者什么情况下,链接载入哪个动态链接库函数。你可以有一个相当大的软件,但每次运行的时候,由于不同的操作需求,只有一小部分程序被载入内存。所有的函数本着“有需求才调入”的原则,于是大大节省了系统资源。比如现在的软件通常都能打开若干种不同类型的文件,这些读写操作通常都用动态链接库来实现。在一次运行当中,一般只有一种类型的文件将会被打开。所以直到程序知道文件的类型以后再载入相应的读写函数,而不是一开始就将所有的读写函数都载入,然后才发觉在整个程序中根本没有用到它们。

三、动态链接库的创建

由于动态链接库函数的共享特性,它们不会被拷贝到可执行文件中。在编译的时候,编译器只会做一些函数名之类的检查。在程序运行的时候,被调用的动态链接库函数被安置在内存的某个地方,所有调用它的程序将指向这个代码段。因此,这些代码必须实用相对地址,而不是绝对地址。在编译的时候,我们需要告诉编译器,这些对象文件是用来做动态链接库的,所以要用地址不无关代码(Position Independent Code (PIC))。

对gcc编译器,只需添加上 -fPIC 标签,如:

gcc -fPIC -c file1.c

gcc -fPIC -c file2.c

gcc -shared lib.so file1.o file2.o

注意到最后一行,-shared 标签告诉编译器这是要建立动态链接库。这与静态链接库的建立很不一样,后者用的是 ar 命令。也注意到,动态链接库的名字形式为 “lib.so” 后缀名为 “.so”

四、动态链接库的使用

使用动态链接库,首先需要在编译期间让编译器检查一些语法与定义。

这与静态库的实用基本一样,用的是 -Lpath 和 -l 标签。如:

gcc file1.o file2.o -Lpath -l -o program.exe

编译器会先在path文件夹下搜索lib.so文件,如果没有找到,继续搜索lib.a(静态库)。

在程序运行期间,也需要告诉系统去哪里找你的动态链接库文件。在UNIX下是通过定义名为 LD_LIBRARY_PATH 的环境变量来实现的。只需将path赋值给此变量即可。csh 命令为:

setenv LD_LIBRARY_PATH   your/full/path/to/dll

一切安排妥当后,你可以用 ldd 命令检查是否连接正常。

ldd program.exe

动态链接库*.so的编译与使用- –

动态库*.so在linux下用c和c++编程时经常会碰到,最近在网站找了几篇文章介绍动态库的编译和链接,总算搞懂了这个之前一直不太了解得东东,这里做个笔记,也为其它正为动态库链接库而苦恼的兄弟们提供一点帮助。

1、动态库的编译

下面通过一个例子来介绍如何生成一个动态库。这里有一个头文件:so_test.h,三个.c文件:test_a.c、test_b.c、test_c.c,我们将这几个文件编译成一个动态库:libtest.so。

so_test.h:

#include   “stdio.h”

void test_a();

void test_b();

void test_c();

test_a.c:

#include “so_test.h”

void test_a()

{

printf(“this is in test_a…/n”);

}

test_b.c:

#include “so_test.h”

void test_b()

{

printf(“this is in test_b…/n”);

}

test_a.c:

#include “so_test.h”

void test_c()

{

printf(“this is in test_c…/n”);

}

将这几个文件编译成一个动态库:libtest.so

$ gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so

2、动态库的链接

在1、中,我们已经成功生成了一个自己的动态链接库libtest.so,下面我们通过一个程序来调用这个库里的函数。程序的源文件为:test.c。

test.c:

#include “so_test.h”

int main()

{

test_a();

test_b();

test_c();

return 0;

}

l 将test.c与动态库libtest.so链接生成执行文件test:

$ gcc test.c -L. -ltest -o test

l 测试是否动态连接,如果列出libtest.so,那么应该是连接正常了

$ ldd test

l 执行test,可以看到它是如何调用动态库中的函数的。

3、编译参数解析

最主要的是GCC命令行的一个选项:

-shared 该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件

l -fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。

l -L.:表示要连接的库在当前目录中

l -ltest:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称

l LD_LIBRARY_PATH:这个环境变量指示动态连接器可以装载动态库的路径。

l 当然如果有root权限的话,可以修改/etc/ld.so.conf文件,然后调用 /in/ldconfig来达到同样的目的,不过如果没有root权限,那么只能采用输出LD_LIBRARY_PATH的方法了。

4、注意

调用动态库的时候有几个问题会经常碰到,有时,明明已经将库的头文件所在目录 通过 “-I” include进来了,库所在文件通过 “-L”参数引导,并指定了“-l”的库名,但通过ldd命令察看时,就是死活找不到你指定链接的so文件,这时你要作的就是通过修改 LD_LIBRARY_PATH或者/etc/ld.so.conf文件来指定动态库的目录。通常这样做就可以解决库无法链接的问题了。

-lxx

xx是你的.so文件名

其实使用方法和你使用数学库函数是一样的,

源代码

中添加

#include ,编译的时候,加上-lm参数。

注:linux下的.so文件为共享库,相当于windows下的dll文件。

扩展资料: 

linux下编写调用so文件实例

.so是Linux(Unix)下的

动态链接库

. 和.dll类似. 

比如:

文件有: a.c, b.c, c.c 

gcc -c a.c 

gcc -c b.c 

gcc -c c.c 

gcc -shared libXXX.so a.o b.o c.o 

要使用的话也很简单. 比如编译d.c, 使用到libXXX.so中的函数, libXXX.so地址是MYPATH 

gcc d.c -o d -LMYPATH -lXXX 

注意不是-llibXXX

test.c文件和一个test.h,这两个文件要生成libsotest.so文件。然后我还有一个testso.c文件,在这个文件里面调用libsotest.so中的函数。

编写的过程中,首先是编译so文件,我没有编写makefile文件,而是参考的2里面说的直接写的gcc命令。

因为so文件里面没有

main函数

,所以是不可执行的,所以编译的时候要加上-c,只生成目标文件。

linux下的.so文件为共享库,相当于windows下的dll文件,使用方法如下:

在你的工程源代码里包含.h头文件,然后可以调用动态库里的函数,在链接的时候加上如下编译器参数:

-l xx.so

如果你的so文件是以lib开头的,还可以直接这样使用:

-lxx

xx是你的.so文件名

其实使用方法和你使用数学库函数是一样的,源代码中添加

#include ,编译的时候,加上-lm参数。

动态链接库,调用,写c语言时用的。放在编译的文件夹里面。包含进去.h就行了、、、、、、、、

安装个开发工具 然后编译就行了 redhat在安装的时候选择自定义就可以安装开发工具 make 然后make install

关于linux查看so接口函数的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » 轻松学会Linux下查看SO接口函数方法 (linux查看so接口函数)