一、-fpic是什么
-fpic是GCC的一个编译选项,全称是position-independent code,即生成位置无关代码。该选项会使得编译器生成不依赖于特定内存地址的可执行文件,使得程序可以在不同的内存位置上执行。
二、-fpic与-fPIC有何区别
与-fPIC相比,-fpic只要求动态库代码段内部的相对指针是位置无关的,而不需要整个数据段都是位置无关的。而-fPIC则要求整个数据段都是位置无关的。因此,编译使用-fpic选项生成代码比使用-fPIC选项生成代码的性能稍低,因为-fpic生成的代码中需要使用runtime重定位,而-fPIC则在链接时进行重定位。
三、如何使用-fpic
在Linux下,使用-fpic选项来编译动态链接库并不困难。如下所示:
gcc -shared -fPIC -o libfoo.so foo.c
在上面的代码中,参数-shared表示编译为动态链接库,-o用来指定生成文件的文件名,libfoo.so即生成的动态链接库的文件名;foo.c则是需要编译的源代码文件。
四、-fpic常见的应用场景
1、动态链接库编译
-fpic选项是动态链接库编译的必备条件,因为生成的动态链接库需要在各种环境下加载,可能使用不同的地址空间。如果动态库的代码不是位置无关的,那么在不同的进程中,它将会被分配到不同的地址。
2、使用dlopen函数动态加载代码
dlopen函数是动态加载代码的常用方式,该函数加载动态链接库并返回一个函数句柄,然后可以使用这个函数句柄调用动态库中的函数。在使用dlopen时,如果没有使用-fpic编译动态库,会导致动态库不能被加载的问题。
3、实现远程过程调用(RPC)
在使用RPC时,客户端和服务器通常运行在不同的机器上。如果使用-fpic选项编译,就能够保证代码段位置无关,从而实现代码在不同的机器上的运行。
五、实例代码
预先定义动态链接库test.c代码如下:
#include
int add(int a, int b)
{
return a+b;
}
int sub(int a, int b)
{
return a-b;
}
编译动态链接库步骤:
gcc -shared -fPIC -o libtest.so test.c
动态链接库生成的代码可以使用以下命令进行查看:
objdump -d -M intel libtest.so
你可以使用以下代码在代码中使用动态链接库中的函数:
#include
#include
int main()
{
void *handle = dlopen("./libtest.so", RTLD_LAZY);
if(!handle)
{
printf("Failed to load dynamic library error:%s\n", dlerror());
return -1;
}
typedef int(*addfun)(int, int);
addfun addfunc = (addfun)dlsym(handle, "add");
if(!addfunc)
{
printf("Failed to find add function error:%s\n", dlerror());
return -1;
}
printf("1+2=%d\n", addfunc(1, 2));
dlclose(handle);
return 0;
}
上面的代码中,dlopen函数动态加载了libtest.so动态链接库,并返回一个句柄。dlsym函数通过句柄查找add函数,并将其函数指针赋值给addfunc。然后我们使用addfunc调用add函数来计算1+2。最后使用dlclose函数关闭动态链接库。
六、小结
-fpic选项是生成位置无关代码和动态链接库的必要条件。因为在动态链接过程中,代码段会被加载到不同的内存地址,而位置无关代码就是为此而设计的,它可以被加载到任意的内存地址上执行,从而增加了代码的可移植性。通过本文的阐述,你已经了解了-fpic选项的含义、应用场景及生成代码的常规流程。如果你希望生成的动态链接库在不同平台上都能正常运行,就必须使用-fpic选项进行编译。
原创文章,作者:ECRYI,如若转载,请注明出处:https://www.506064.com/n/369501.html