-fPIC
-fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。
gcc -shared -fPIC -o 1.so 1.c1
PIC使.so文件的代码段变为真正意义上的共享
如果不加-fPIC,则加载.so文件的代码段时,代码段引用的数据对象需要重定位, 重定位会修改代码段的内容,这就造成每个使用这个.so文件代码段的进程在内核里都会生成这个.so文件代码段的copy.每个copy都不一样,取决于 这个.so文件代码段和数据段内存映射的位置. 也就是不加fPIC编译出来的so,是要再加载时根据加载到的位置再次重定位的.(因为它里面的代码并不是位置无关代码) 如果被多个应用程序共同使用,那么它们必须每个程序维护一份.so的代码副本了.(因为.so被每个程序加载的位置都不同,显然这些重定位后的代码也不同,当然不能共享)
我们总是用fPIC来生成so,也从来不用fPIC来生成.a;fPIC与动态链接可以说基本没有关系,libc.so一样可以不用fPIC编译,只是这样的so必须要在加载到用户程序的地址空间时重定向所有表目.
因此,不用fPIC编译so并不总是不好.
如果你满足以下4个需求/条件:
1.该库可能需要经常更新
2.该库需要非常高的效率(尤其是有很多全局量的使用时)
3.该库并不很大.
4.该库基本不需要被多个应用程序共享如果用没有加这个参数的编译后的共享库,也可以使用的话,可能是两个原因:
1:gcc默认开启-fPIC选项
2:loader使你的代码位置无关
从GCC来看,shared应该是包含fPIC选项的,但似乎不是所以系统都支持,所以最好显式加上fPIC选项。参见如下:
`-shared'
Produce a shared object which can then be linked with other
objects to form an executable. Not all systems support this
option. For predictable results, you must also specify the same
set of options that were used to generate code (`-fpic', `-fPIC',
or model suboptions) when you specify this option.(1)123456
-fPIC 的使用,会生成 PIC 代码,.so 要求为 PIC,以达到动态链接的目的,否则,无法实现动态链接。
-Wno-deprecated
忽略编译警告
-D_REENTRANT 宏作用
在一个多线程程序里,默认情况下,只有一个errno变量供所有的线程共享。在一个线程准备获取刚才的错误代码时,该变量很容易被另一个线程中的函数调用所改变。类似的问题还存在于fputs之类的函数中,这些函数通常用一个单独的全局性区域来缓存输出数据。
为解决这个问题,需要使用可重入的例程。可重入代码可以被多次调用而仍然工作正常。编写的多线程程序,通过定义宏_REENTRANT来告诉编译器我们需要可重入功能,这个宏的定义必须出现于程序中的任何#include语句之前。
_REENTRANT为我们做三件事情,并且做的非常优雅:
-
它会对部分函数重新定义它们的可安全重入的版本,这些函数名字一般不会发生改变,只是会在函数名后面添加_r字符串,如函数名gethostbyname变成gethostbyname_r。
-
stdio.h中原来以宏的形式实现的一些函数将变成可安全重入函数。
-
在error.h中定义的变量error现在将成为一个函数调用,它能够以一种安全的多线程方式来获取真正的errno的值
-D_POSIX_C_SOURCE=199506L
glibc是GNU发布的libc库,即c运行库。glibc是系统中最底层的api,几乎其它任何运行库都会依赖于glibc。
POSIX.1-2001中未指定O_CLOEXEC,O_DIRECTORY和O_NOFOLLOW标志,但在POSIX.1-2008中指定 . 由于glibc 2.12,可以通过定义大于或等于200809L的_POSIX_C_SOURCE或大于或等于700的_XOPEN_SOURCE来获得它们的定义 . 在glibc 2.11和更早版本中,通过定义_GNU_SOURCE获得定义 .
尝试使用 -D_POSIX_C_SOURCE=200809L进行编译或在包含任何 Headers 之前添加#define _POSIX_C_SOURCE 200809L .
判断操作系统
uname_S:=$(shell sh -c 'uname -s 2>/dev/null || echo not')
-i,-l,-L
-i:指定头文件所在目录
-l:指定库名
-L:指定库所在目录
-fPIC选项用于生成位置无关代码,使得代码可以在内存的任意位置正确执行,适合共享库。不使用-fPIC可能导致每个使用共享库的进程都有代码副本。在多线程编程中,_REENTRANT宏确保可重入函数的安全。-D_POSIX_C_SOURCE宏影响对特定POSIX标准标志的支持。文章讨论了这些编译选项和宏在Linux系统编程中的重要性。
1223





