Linux环境下共享库(动态链接库)的简要介绍(如何创建共享库)

库是把各种编译后的目标文件包含一起的文件。包含一组特定环境下使用的函数。例如,'pthread'库包含线程相关的函数,可用于带有线程功能的程序中。


一般来说,库(或者说程序库)有两种类型:

1)共享库

2)静态库


本文介绍共享库。


共享库可以在程序运行阶段动态链接进入到程序中。提供了可以把代码加载到内存任意位置的一个方法。一旦加载,共享库的代码可以用于多个程序。所以,因为代码可以在多个程序中共享,用这种方法编译的程序会显著变小。


。。。。。共享库可以通过如下三种命名方法来访问:

1)链接器(linker)使用的名字('lib'后跟着库名字,再加上.so后缀,例如libpthread.so)

2)  Fully qualified name or soname( 'lib'后跟着库名字,再加上.so后缀,最后加上.和版本号码,例如:libpthread.so.1)

3)真实名字('lib'后跟着库名字,加上.so后缀,加上点和版本号码,加上点和次版本号码,最后还可以跟点和发布版本,发布版本不是必须的,例如libpthread.so.1.1)


版本号(译者注:即主版本号)当新版本的库与上一个版本的库不兼容时,则需要改变版本号,例如新版本中把一个函数完全移除掉了,则主版本号需要变更。

次版本号用于表示微小变更,不影响兼容性的。例如一个会引起系统崩溃的小bug被修复了。

。。。。。。。


链接器使用的名字,通常是一个符号链接,其指向了一个Fully qualified name or soname,这个也是一个符号链接,其指向一个真实的名字。


在系统中摆放的位置

有三个标准位置:

1)/lib

2)  /usr/lib

3)  /usr/local/lib


。。。。。第三个位置用于保存正式发布以外的库。


使用ldconfig

创建了共享库后,把它拷贝到某个目录下,例如/usr/local/lib 或者/usr/lib.  在这个目录下运行ldconfig.


ldconfig用来做什么的呢?


。。。。。。


当运行一个ELF可执行文件时,缺省情况下加载器(loader)会首先运行起来,加载器本身也是一个共享库 /lib/ld-linux.so.X,这里X表示版本号. 加载器来寻找和加载程序中依赖的其它共享库。


加载器根据/etc/ld.so.conf文件中规定的目录去搜选共享库。搜寻/etc/ld.so.conf文件中规定的所有目录是非常耗时的。 ldconfig用于创建动态库的cache,保存到/etc/ld.so.cache.  所以,在程序开始运行时,加载器到/etc/ld.so.cache去加载需要的共享库。


........


例子(如何创建共享库



#include "shared.h"
unsigned int add(unsigned int a, unsigned int b)
{
    printf("\n Inside add()\n");
    return (a+b);
}

shared.h looks like :

#include<stdio.h>
extern unsigned int add(unsigned int a, unsigned int b);

创建共享库的命令:

gcc -c -Wall -Werror -fPIC shared.c
gcc -shared -o libshared.so shared.o

编写一个使用共享库中函数的例子

#include<stdio.h>
#include"shared.h"
int main(void)
{
    unsigned int a = 1;
    unsigned int b = 2;
    unsigned int result = 0;

    result = add(a,b);

    printf("\n The result is [%u]\n",result);
    return 0;
}
编译主程序:

gcc -L/home/himanshu/practice/ -Wall main.c -o main -lshared
-lshared  表示使用libshared.so共享库,在_L指定的目录中/home/himanshu/practice/


把库目录export到环境变量中(在程序执行时以便程序能找到共享库)


export LD_LIBRARY_PATH=/home/himanshu/practice:$LD_LIBRARY_PATH
运行并打印出结果:


# ./main

Inside add()

The result is [3]



原文如下:http://www.thegeekstuff.com/2012/06/linux-shared-libraries/


Intro to Linux Shared Libraries (How to Create Shared Libraries)

A library is a file containing compiled code from various object files stuffed into a single file. It may contain a group of functions that are used in a particular context. For example, the ‘pthread’ library is used when thread related functions are to be used in the program.

Broadly, a library (or Program Library) can be of two types :

  1. Shared Library
  2. Static Library

In this article we will discuss specifically about Shared Libraries.

Shared Libraries

Shared Libraries are the libraries that can be linked to any program at run-time. They provide a means to use code that can be loaded anywhere in the memory. Once loaded, the shared library code can be used by any number of programs. So, this way the size of programs(using shared library) and the memory footprint can be kept low as a lot of code is kept common in form of a shared library.

Shared libraries provide modularity to the development environment as the library code can be changed, modified and recompiled without having to re-compile the applications that use this library. For example, for any change in the pthread library code, no change is required in the programs using pthread shared library. A shared library can be accessed through different names :

  • Name used by linker (‘lib’ followed by the library name, followed by ‘.so’ . For example libpthread.so)
  • Fully qualified name or soname ( ‘lib’ followed by the library name, followed by ‘.so’, followed by ‘.’ and a version number. For example : libpthread.so.1)
  • Real name (‘lib’ followed by the library name, followed by ‘.so’, followed by ‘.’ and a version number, followed by a ‘.’ and a minor number, followed by a ‘.’ and a release number. Release number is optional. For example, libpthread.so.1.1)

A version number is changed for a shared library when the changes done in the code make the shared library incompatible with the previous version. For example, if a function is completely removed then a new version of the library is required.

A minor number is changed in case there is a modification in the code that does not make the shared library incompatible with the previous version being used. For example, a small bug fix won’t break the compatibility of the existing shared library so only a minor number is changed while version remains the same.

Now, one may wonder why so many names for a shared library?

Well, these naming conventions help multiple versions of same shared library to co-exist in a system. The programs linking with the shared library do not need to take care about the latest version of the shared library installed in the system. Once the latest version of the shared library is installed successfully, all the programs automatically start linking to the latest version.

The name used by linker is usually a symbolic link to the fully qualified soname which in turn is a symbolic link to the real name.

Placement in File System

There are mainly three standard locations in the filesystem where a library can be placed.

  • /lib
  • /usr/lib
  • /usr/local/lib

We will go by the Filesystem Hierarchy standards(FHS) here. According to the FHS standards, All the libraries which are loaded at start up and running in the root filesystem are kept in /lib. While the libraries that are used by system internally are stored at /usr/lib. These libraries are not meant to be directly used by users or shell scripts. There is a third location /usr/local/lib( though it is not defined in the latest version of FHS ). If it exists, it contains all the libraries that are not part of standard distribution. These non-standard libraries are the one’s which you download and could be possibly buggy.

Using ldconfig

Once a shared library is created, copy the shared library to directory in which you want the library to reside (for example /usr/local/lib or /usr/lib). Now, run ldconfig command in this directory.

What does ldconfig do?

You remember that we discussed earlier that a linker name for shared library is a symbolic link to the fully qualified soname which in turn is a symbolic link to the real name. Well, this command does exactly the same.

When you run an ELF executable, by default the loader is run first. The loader itself is a shared object file /lib/ld-linux.so.X where ‘X’ is a version number. This loader in turn finds and loads all the shared libraries on which our program depends.

All the directories that are searched by the loader in order to find the libraries is stored in /etc/ld.so.conf. Searching all the directories specified in /etc/ld.so.conf file can be time consuming so every time ldconfig command is run, it sets up the required symbolic links and then creates a cache in file /etc/ld.so.cache where all the information required for executable is written. Reading information from cache is very less time consuming. The catch here is that ldconfig command needs to be run every-time a shared library is added or removed. So on start-up the program uses /etc/ld.so.cache to load the libraries it requires.

Using Non Standard Library Locations

When using non standard library locations. One of the following three steps could be carried out :

Add the path to /etc/ld.so.conf file. This file contains paths to all the directories in which the library is searched by the loader. This file could sometime contain a single line like :

include /etc/ld.so.conf.d/*.conf

In that case, just create a conf file in the same directory. You can directly add a directory to cache by using the following command :

ldconfig -n [non standard directory path containing shared library]

Note that this is a temporary change and will be lost once the system is rebooted. Update the environment variable LD_LIBRARY_PATH to point to your directory containing the shared library. Loader will use the paths mentioned in this environment variable to resolve dependencies.

Note that on some Unix systems the name of the environment variable could differ.

Note: On a related topic, as we explained earlier, there are four main stages through which a source code passes in order to finally become an executable.

Example (How to Create a Shared Library)

Lets take a simple practical example to see how we can create and use shared libraries. The following is the piece of code (shared.c) that we want to put in a shared library :

#include "shared.h"
unsigned int add(unsigned int a, unsigned int b)
{
    printf("\n Inside add()\n");
    return (a+b);
}

shared.h looks like :

#include<stdio.h>
extern unsigned int add(unsigned int a, unsigned int b);

Lets first make shared.c as a shared library.

1. Run the following two commands to create a shared library :

gcc -c -Wall -Werror -fPIC shared.c
gcc -shared -o libshared.so shared.o

The first command compiles the code shared.c into position independent code which is required for a shared library.
The second command actually creates a shared library with name ‘libshared.so’.

2. Here is the code of the program that uses the shared library function ‘add()’

#include<stdio.h>
#include"shared.h"
int main(void)
{
    unsigned int a = 1;
    unsigned int b = 2;
    unsigned int result = 0;

    result = add(a,b);

    printf("\n The result is [%u]\n",result);
    return 0;
}

3. Next, run the following command :

gcc -L/home/himanshu/practice/ -Wall main.c -o main -lshared

This command compiles the main.c code and tells gcc to link the code with shared library libshared.so (by using flag -l) and also tells the location of shared file(by using flag -L).

4. Now, export the path where the newly created shared library is kept by using the following command :

export LD_LIBRARY_PATH=/home/himanshu/practice:$LD_LIBRARY_PATH

The above command exports the path to the environment variable ‘LD_LIBRARY_PATH’.

5. Now run the executable ‘main’ :

# ./main

Inside add()

The result is [3]

So we see that shared library was loaded and the add function inside it was executed.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值