我是个C编程新手,对.so文件一无所知.这有什么必要呢?我如何创建它?如何绑定我的C代码或二进制与它?如果我不做任何.so文件,直接做C代码的可执行二进制文件,它的优点和缺点是什么?我需要一个详细的描述。
nr7wwzry1#
.so文件是共享对象。通常共享库是.so。通过将库设置为.so,可以提高内存使用效率。即,当使用该库的多个应用程序正在运行时,与静态库的情况相反,该库仅被加载到存储器中一次。创建动态库:
.so
gcc -Wall -fPIC -c *.c gcc -shared -Wl,-soname,libctest.so.1 -o libctest.so.1.0 *.o
-fPIC:输出位置无关代码的编译器指令,这是共享库所需的特性。-shared:生成一个共享对象,然后可以与其他对象链接以形成可执行文件。
-fPIC
-shared
您可以查看更多信息here。
tkqqtvp12#
.so代表共享对象。在Windows世界中,这被称为DLL。您可以使用它的方式与使用DLL的方式几乎相同-您可以将应用程序动态链接到它。如果你的库名为libblah.so,你可以像这样使用gcc链接到它:
gcc myprog.c -lblah -o myprog
共享库有助于将公共功能分解到单独的文件中。但是,使用共享库可能会导致称为DLL Hell的现象。虽然这个问题起源于Windows世界,但它也适用于Linux系统,除非您非常密切地关注所使用的共享库的确切版本并实施严格的版本控制。例如,如果您使用共享库(甚至是系统共享库,而不是您创建的库)编译您的应用程序,然后尝试在另一个Linux机器上运行相同的可执行文件(使用完全不同的Linux版本或发行版),它可能无法运行-因为使用的共享库不相同。因此,如果您希望您的可执行文件可以移植到最大数量的Linux系统而无需重新编译,那么静态编译它可能是有意义的。虽然这使您的可执行文件更大,但它确实减少了通常归因于DLL地狱的问题。
weylhg0b3#
除了其他答案之外,请注意,要构建共享对象(或共享库),最好在position independent code模式下编译相关的源文件,如
gcc -Wall -O -fPIC src.c -c -o src.pic.o
在编译一些源代码时,使用-Wall询问所有警告总是很有用的。然后,您可以使用以下命令将所有这些*.pic.o文件链接到.so中
-Wall
*.pic.o
gcc -shared src1.pic.o src2.pic.o -o shared.so
你甚至可以使用链接将一些共享库libfoo.so链接到共享对象中
libfoo.so
gcc -shared src1.pic.o src2.pic.o -lfoo -o shared.so
最后通过dlopen将共享对象动态加载到进程中;这对于得到plugins是有用的。(然后为它们定义一个约定,并使用dlsym在其中获取重要符号)参见program library howto和Executable & Link Format & shared library维基页面在创建共享库时,最好将其命名为libfoo.so,其中 foo 是任意名称。然后,在链接时,也使用-L选项到gcc(实际上是链接器)来告诉包含它的目录,并使用-lfoo 选项链接它。例如,在创建库时将其命名为libnewbie.so,并在链接它时将-L.(如果它在当前目录中)传递到-lnewbie之前,例如。gcc -Wall myprog.c -L. -lnewbie -o myprog
dlsym
lib
-L
gcc
-l
libnewbie.so
-L.
-lnewbie
gcc -Wall myprog.c -L. -lnewbie -o myprog
3条答案
按热度按时间nr7wwzry1#
.so
文件是共享对象。通常共享库是.so
。通过将库设置为
.so
,可以提高内存使用效率。即,当使用该库的多个应用程序正在运行时,与静态库的情况相反,该库仅被加载到存储器中一次。创建动态库:
-fPIC
:输出位置无关代码的编译器指令,这是共享库所需的特性。-shared
:生成一个共享对象,然后可以与其他对象链接以形成可执行文件。您可以查看更多信息here。
tkqqtvp12#
.so
代表共享对象。在Windows世界中,这被称为DLL。您可以使用它的方式与使用DLL的方式几乎相同-您可以将应用程序动态链接到它。
如果你的库名为libblah.so,你可以像这样使用gcc链接到它:
共享库有助于将公共功能分解到单独的文件中。
但是,使用共享库可能会导致称为DLL Hell的现象。虽然这个问题起源于Windows世界,但它也适用于Linux系统,除非您非常密切地关注所使用的共享库的确切版本并实施严格的版本控制。例如,如果您使用共享库(甚至是系统共享库,而不是您创建的库)编译您的应用程序,然后尝试在另一个Linux机器上运行相同的可执行文件(使用完全不同的Linux版本或发行版),它可能无法运行-因为使用的共享库不相同。
因此,如果您希望您的可执行文件可以移植到最大数量的Linux系统而无需重新编译,那么静态编译它可能是有意义的。虽然这使您的可执行文件更大,但它确实减少了通常归因于DLL地狱的问题。
weylhg0b3#
除了其他答案之外,请注意,要构建共享对象(或共享库),最好在position independent code模式下编译相关的源文件,如
在编译一些源代码时,使用
-Wall
询问所有警告总是很有用的。然后,您可以使用以下命令将所有这些
*.pic.o
文件链接到.so
中你甚至可以使用链接将一些共享库
libfoo.so
链接到共享对象中最后通过dlopen将共享对象动态加载到进程中;这对于得到plugins是有用的。(然后为它们定义一个约定,并使用
dlsym
在其中获取重要符号)参见program library howto和Executable & Link Format & shared library维基页面
在创建共享库时,最好将其命名为
lib
foo.so
,其中 foo 是任意名称。然后,在链接时,也使用-L
选项到gcc
(实际上是链接器)来告诉包含它的目录,并使用-l
foo 选项链接它。例如,在创建库时将其命名为libnewbie.so
,并在链接它时将-L.
(如果它在当前目录中)传递到-lnewbie
之前,例如。gcc -Wall myprog.c -L. -lnewbie -o myprog