Linux装载和启动一个可执行程序

来源:互联网 发布:金庸和古龙 知乎 编辑:程序博客网 时间:2024/06/05 20:04

原创作品转载请注明出处
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

几个概念

库文件

程序员可以把自己的代码打包成库文件,再提供一个头文件即可。
库文件包括 静态库和共享库(动态库)。 
静态库的使用方式是代码的复制,共享库的使用方式是函数指针(函数地址)

静态库(.a)

优点:代码独立,效率稍好
缺点:代码的空间太大,不利于修改和维护

共享库(.so)

优先:代码空间较小,修改,维护比较方便
缺点:代码依赖于共享库文件
实际开发中共享库的使用更加广泛

静态库的使用步骤

1 、生成静态库文件(.a)

>写源代码
>编译生成目标文件(.o)
>使用 ar -r 命令生成静态库文件
ar -r lib___.a ____.o

2 、调用静态库文件

(前提:需要 lib__.a 和__.h 文件)
>写调用源代码
>编译(gcc -c)
>链接静态库文件,有三种方式

1.gcc __.o lib__.a(直接连接不推荐)

2.配置环境变量 LIBRARY_PATH,把库文件所在路径配进去然后用 gcc __.c -l__(库文件 lib后面名字)

3.gcc __.o -l__ -L 库文件路径

$cd slib$lsadd.c add.h test.c//编译生成.o 文件$gcc -c add.c$lsadd.c add.h add.o test.c//利用.o 文件生成静态库.a 文件$ar -r libmylib.a add.oar: creating libmylib.a//第一种链接方式/运行$gcc test.c libmylib.a$a.outr1=5,r2=5.000000//第二种链接方式/运行$export LIBRARY_PATH=.$gcc test.c -lmylib$a.outr1=5,r2=5.000000//第三种链接方式/运行$gcc test.c -lmylib -L.$a.outr1=5,r2=5.000000

共享库的使用步骤

1 、生成 共享库文件.so

>写源代码
>编译生成目标文件.o
gcc -c -fpic __.c #-fpic 可以不加
>生成共享库文件
gcc -shared __.o -o lib__.so

2 、调用 共享库文件和静态库一样

注意:要运行共享库程序
必须配置 LD_LIBRARY_PATH
LD_LIBRARY_PATH:
编译没有影响主要影响运行
$lsDprint.c Jprint.c print.h test.c$gcc -c Dprint.c$gcc -shared Dprint.o -o libdt.so$export LD_LIBRARY_PATH=.$gcc test.c -ldt -L.

动态编程

(使用程序直接调用库文件的函数)<dlfcn.h>加载动态库的头文件
步骤:
1.用 dlopen 打开一个库文件,返回 void*即动态库首地址
2.用 dlsym 按函数名打开一个函数,返回函数指针
3.使用函数指针
4.用 dlclose 关闭库文件
5.dlerror 函数判断是否出错,!=NULL 出错

打开库文件
void *dlopen(const char *filename, int flag);
RTLD_LAZY:runtime library dynamic lazy 延迟加载
RTLD_NOW: runtime library dynamic now 直接加载

获取出错信息
char *dlerror(void);<span style="color: rgb(102, 102, 102); font-family: 'Hiragino Sans GB W3', 'Hiragino Sans GB', Arial, Helvetica, simsun, u5b8bu4f53; font-size: 16px; line-height: 28px;">返回NULL 代表没有错</span>
返回NULL 代表没有错

获取库函数指针
void *dlsym(void *handle, const char *symbol);

关闭动态库
int dlclose(void *handle);

void* handle 是 dlopen 的返回值
const char *symbol 是函数名
返回值是函数指针


#include <stdio.h>#include <dlfcn.h>int main(){<span style="white-space:pre"></span>void * handle = dlopen("./libadd.so", RTLD_NOW); <span style="white-space:pre"></span>char* error = dlerror(); <span style="white-space:pre"></span>if (error) <span style="white-space:pre"></span>{  <span style="white-space:pre"></span>printf("open error"); <span style="white-space:pre"></span>return -1; <span style="white-space:pre"></span>}<span style="white-space:pre"></span>//int print(int,int);函数原型<span style="white-space:pre"></span>int (*f)(int, int); //函数指针,函数名用*f替换函数名<span style="white-space:pre"></span>f = dlsym(handle, "add");<span style="white-space:pre"></span>if (error)<span style="white-space:pre"></span>{  <span style="white-space:pre"></span>printf("sym error\n");  <span style="white-space:pre"></span>return -1; <span style="white-space:pre"></span>} <span style="white-space:pre"></span>int r = f(1, 2); <span style="white-space:pre"></span>printf("r=%d\n", r); <span style="white-space:pre"></span>dlclose(handle); <span style="white-space:pre"></span>return 0;}





0 0
原创粉丝点击