📓 Archive

  • Pricing
  • Chess
  • Syntax
  • LIBRARY

    FGJ: Create:2023/12/08 Update: [2024-11-23]

    Linux共享库,静态库,动态链接库 #

    • 介绍 #

      程序函数库可分为3种类型:静态函数库(static libraries)、共享函数库(shared libraries)、动态加载函数库(dynamically loaded libraries):

      1. 静态函数库,是在程序执行前就加入到目标程序中去了 ;
      2. 动态函数库同共享函数库是一个东西(在linux上叫共享对象库, 文件后缀是.so ,windows上叫动态加载函数库, 文件后缀是.dll)
      • linux中明明系统的共享库的规则

    • 代码实现 #

      libhello.c

      /* libhello.c - demonstrate library use. */
      #include <stdio.h>
      
      void hello(void) {
          printf("Hello, library world.\n");
      }
      

      libhello.h

      /* libhello.h - demonstrate library use. */
      
      void hello(void);
      

      demo_use.c

      /* demo_use.c -- demonstrate direct use of the "hello" routine */
      #include "libhello.h"
      
      int main(void) {
          hello();
          return 0;
      }
      
      # Static library demo
      
      # Create static library's object file, libhello-static.o.
      # I'm using the name libhello-static to clearly
      # differentiate the static library from the
      # dynamic library examples, but you don't need to use
      # "-static" in the names of your
      # object files or static libraries.
      
      # -Wall: 这个选项会开启编译器的所有警告信息。它告诉编译器在编译过程中显示尽可能多的警告,帮助开发者发现潜在的问题。
      # -g: 这个选项生成用于调试的额外信息,包括源代码中的行号、变量名称等。这些信息会被包含在目标文件中,便于调试程序。
      # -c: 这个选项告诉编译器只进行编译,而不进行链接。它会将源文件编译成目标文件,但不会生成可执行文件。
      gcc -Wall -g -c -o libhello-static.o libhello.c
      
      # Create static library.
      ar rcs libhello-static.a libhello-static.o
      
      # At this point we could just copy libhello-static.a
      # somewhere else to use it.
      # For demo purposes, we'll just keep the library
      # in the current directory.
      
      # Compile demo_use program file.
      
      gcc -Wall -g -c demo_use.c -o demo_use.o
      
      # Create demo_use program; -L. causes "." to be searched during
      # creation of the program.  Note that this command causes
      # the relevant object file in libhello-static.a to be
      # incorporated into file demo_use_static.
      
      # -L.: 这个选项告诉链接器在当前目录 (.) 中查找库文件。
      # -lhello-static: 这个选项告诉链接器要链接名为 libhello-static.a 或 libhello-static.so 的库文件。
      gcc -g -o demo_use_static demo_use.o -L. -lhello-static
      
      # Execute the program.
      
      ./demo_use_static
      

      static 中 删除中间对象,比如rm -f libhello-static.a libhello-static.o 后,编译出来的 demo_use_static也可以正常执行。

      ar 归档工具的作用就是将多个.o文件压缩到一个.a文件中(包括一些额外的元信息)。方便使用 -l.a.o文件进行链接。
      ⫸ 如果只有单个.o文件的话,直接链接,不使用任何参数:gcc -g -o main demo_use.o libhello-static.o

      # Shared library demo
      
      # Create shared library's object file, libhello.o.
      
      # -fPIC: 这个选项告诉编译器生成位置独立的代码[位置无关](Position Independent Code)。生成的代码可在内存中的任何位置运行,通常用于动态链接库(如共享库)的生成。
      gcc -fPIC -Wall -g -c libhello.c
      
      # Create shared library.
      # Use -lc to link it against C library, since libhello
      # depends on the C library.
      
      # -g: 这个选项生成用于调试的额外信息,包括源代码中的行号、变量名称等。这些信息会被包含在目标文件中,便于调试程序。
      # -shared: 这个选项告诉编译器生成一个共享库。
      # -Wl,-soname,libhello.so.0: -Wl 是传递选项给链接器的方式。-soname 选项设置共享库的 soname(符号名)。这里指定了 libhello.so.0 作为 soname。
      # -o libhello.so.0.0: 这个选项指定生成的共享库文件名为 libhello.so.0.0。
      # libhello.o: 这是要链接的目标文件的名称(libhello.o)。
      # -lc: 这个选项告诉链接器(ld)在链接时需要链接 C 标准库(libc.so)。
      # 综合起来,这条命令告诉编译器 gcc 使用 -g 选项生成共享库,并指定共享库的 soname 为 libhello.so.0,然后将 libhello.o 目标文件链接到一个名为 libhello.so.0.0 的共享库中,并将 C 标准库链接到生成的共享库中。
      gcc -g -shared -Wl,-soname,libhello.so.0  -o libhello.so.0.0 libhello.o -lc
      
      # At this point we could just copy libhello.so.0.0 into
      # some directory, say /usr/local/lib.
      
      # Now we need to call ldconfig to fix up the symbolic links.
      
      # Set up the soname.  We could just execute:
      # ln -sf libhello.so.0.0 libhello.so.0
      # but let's let ldconfig figure it out.
      
      # /sbin/ldconfig 命令用于配置动态链接器运行时的链接库。在这个命令中,-n 选项告诉 ldconfig 不要实际更改系统配置,而是显示将要执行的操作。
      # . 表示当前目录。ldconfig 命令在运行时会扫描指定的目录,查找可执行文件需要的共享库,并更新系统的共享库缓存,使得系统能够正确地找到和链接这些共享库。
      # 但是在这个命令中,由于使用了 -n 选项,它只是展示了在当前目录运行 ldconfig 实际会执行的操作,而不会实际执行更新系统共享库缓存的操作。
      
      # 以上解释应该是有问题的。实际情况是 生成了一个 libhello.so.0的软连接
      /sbin/ldconfig -n .
      
      # Set up the linker name.
      # In a more sophisticated setting, we'd need to make
      # sure that if there was an existing linker name,
      # and if so, check if it should stay or not.
      
      ln -sf libhello.so.0 libhello.so
      
      # Compile demo_use program file.
      
      gcc -Wall -g -c demo_use.c -o demo_use.o
      
      # Create program demo_use.
      # The -L. causes "." to be searched during creation
      # of the program; note that this does NOT mean that "."
      # will be searched when the program is executed.
      
      gcc -g -o demo_use demo_use.o -L. -lhello
      
      # Execute the program.  Note that we need to tell the program
      # where the shared library is, using LD_LIBRARY_PATH.
      
      LD_LIBRARY_PATH="." ./demo_use
      

      demo_dynamic.c

      /* demo_dynamic.c -- demonstrate dynamic loading and use of the "hello" routine */
      
      /* Need dlfcn.h for the routines to dynamically load libraries */
      #include <dlfcn.h>
      
      #include <stdlib.h>
      #include <stdio.h>
      
      /* Note that we don't have to include "libhello.h". However, we do need to specify something related;
      we need to specify a type that will hold the value we're going to get from dlsym(). */
      
      /* The type "simple_demo_function" describes a function that takes no arguments, and returns no value: */
      typedef void (*simple_demo_function)(void);
      
      int main(void) {
          const char *error;
          void *module;
          simple_demo_function demo_function;
      
          /* Load dynamically loaded library */
          module = dlopen("libhello.so", RTLD_LAZY);
          if (!module) {
              fprintf(stderr, "Couldn't open libhello.so: %s\n", dlerror());
              exit(1);
          }
      
          /* Get symbol */
          dlerror();
          demo_function = dlsym(module, "hello");
          if ((error = dlerror())) {
              fprintf(stderr, "Couldn't find hello: %s\n", error);
              exit(1);
          }
      
          /* Now call the function in the DL library */
          (*demo_function)();
      
          /* All done, close things cleanly */
          dlclose(module);
          return 0;
      }
      
      #!/bin/sh
      # Dynamically loaded library demo
      
      # Presume that libhello.so and friends have been created (see dynamic example).
      
      # Compile demo_dynamic program file into an object file.
      
      gcc -Wall -g -c demo_dynamic.c
      
      # Create program demo_use.
      # Note that we don't have to tell it where to search for DL libraries,
      # since the only special library this program uses won't be loaded until after the program starts up.
      # However, we DO need the option -ldl to include the library that loads the DL libraries.
      
      gcc -g -o demo_dynamic demo_dynamic.o -ldl
      
      # Execute the program.  Note that we need to tell the
      # program where get the dynamically loaded library,
      # using LD_LIBRARY_PATH.
      
      LD_LIBRARY_PATH="." ./demo_dynamic
      

    Reference #


    comments powered by Disqus