linux下的 lib文件的学习思考

说到这个LIB文件,先从一个小故障说起。

某日开发说,一台测试用虚机可以PING通SSH不能连了。运维同学就赶紧去查,SSHD_CONFIG配置文件都正确啊,一点错误都没有,那为什么呢?

测试下,不管连自己还是其他机,都是报错

这里注意看,提示你有个libcom_err.so.2共享库文件找不到。

询问开发,才了解他们测试一个软件,意外删除了某个库文件。

那么在正常的相同虚机的机器查看下,再和出错的虚机比对下,发现少了2个库文件

挂载系统光盘或从正常的虚机上把这个两个文件拷贝过来,放到lib64下就可以了

再试正常了

这个小故障很容易解决,那么你怎么理解linux中的库文件呢?学习下也不误工作。

Linux下的库文件分为共享库和静态库两大类,它们两者的差别仅在程序执行时所需的代码是在运行时动态加载的,还是在编译时静态加载的。 

Linux的库一般在/lib 或/usr/lib 目 录下,如果是64位的系统则会有lib64目录。lib是库(Library)的英文缩写,它主要存放系统的链接库文件,没有该目录则系统就无法正常运行。/lib目录中存储着程序运行时使用的共享库。通过共享库,许多程序可以重复使用相同的代码,并且这些库可以存储在一个公共的位置上,因此能减小运行程序的大小。这个目录包含程序在链接时使用的 各种库。

库的知识

1.库的命名

库的命名比较简单,第一个特点是所有的库以lib开头,GCC命令在在-l选项所指定的文件名前会自动加入lib。

第二个特点文件名以.a结尾的库是静态库。

第三个特点文件名是.so的库为共享库(共享库是在运行的时候动态加载的 )。默认情况下,GCC在链接时优先使用共享库,只有当共享库不存在时才考虑使用静态库。 

2、库的编号

库的编号格式如下:  library_name .major.num .minor_.min .pathch_num 例如,笔者Red Hat Linux 9.0的GUN数据库是libgdbm.so.0.0.2,详细表述如下: ◆library_name是libc.so(标准C库); ◆major_num是2(主版本号); ◆minor_.min是0(次版本号); ◆pathch_num是0(补丁级别号又称发行号)。

3、库的操作命令

Linux库操作可以使用命令完成,目前常用的命令是ldd和ldconfig。 ldd 是Library Dependency Display缩写,它的作用是显示一个可执行程序必须使用的共享库 。 (1)命令格式 ldd [选项] 文件名 (2)主要参数 -d 执行重定位并报告丢失的函数。 -r 执行对函数和数据对象的重定位,并报告丢失的函数和数据对象。

(3)应用举例

比如查询Perl语言有哪些共享库,则可以首先使用find命令查询这个程序的绝对路径,然后使用ldd命令: #find -name perl ldd /usr/bin/perl

$ ldd test 执行test,可以看到它是如何调用动态库中的函数的。

2.ldconfig ldconfig 命令的作用是决定位于目录/usr/lib和/lib下的共享库所需的运行链接。这些链接保存在的Libs保存在/et/ld.so.conf文件中。搜 索出可共享的动态链接库(格式如前介绍,lib*.so*),进而创建出动态装入程序(ld.so)所需的链接和缓存文件。缓存文件默认为/etc /ld.so.cache,此文件保存已排好序的动态链接库名字列表。 (1)命令格式 ldconfig [选项] [libs] (2)主要选项  -v或--verbose ldconfig将显示正在扫描的目录、搜索到的动态链接库,以及它所创建的连接的名字。  -f CONF 指定动态链接库的配置文件为CONF,系统默认为/etc/ld.so.conf。  -C CACHE 指定生成的缓存文件为CACHE,系统默认的是/etc/ld.so.cache,文件存放已排好序的可共享的动态链接库的列表。  -p或--print-cache 让ldconfig打印出当前缓存文件所保存的所有共享库的名字。  -r ROOT 改变应用程序的根目录为ROOT。  -n ldconfig仅扫描命令行指定的目录,不扫描默认目录(/lib、/usr/lib),也不扫描配置文件/etc/ld.so.conf所列的目录。  运行没有选项的ldconfig命令时,用于更新高速缓冲文件。这个命令主要用于高速缓冲DNS服务器(Caching DNS Server)。高速缓冲DNS服务器的原理是提供查询的历史记录,并且利用这些记录来提高查询的效率。  当某个查询是第一次被发送到高速缓冲DNS服务器时,高速缓冲DNS服务器就将此查询的整个过程记录下来,在一定的时期内用它来回答所有相同的查询,从而减少整个DNS系统的负担并且提高查询速度。  (3)应用实例  如果用户想知道系统中有哪些动态链接库,或者想知道系统中有没有某个动态链接库时,可用-p选项让ldconfig输出缓存文件中的动态链接库列表,从而查询得到。 例如:

ldconfig -p 998 libs found in cache `/etc/ld.so.cache' libzvt.so.2 (libc6) => /usr/lib/libzvt.so.2 libzvt.so (libc6) => /usr/lib/libzvt.so ……

补充:

静态链接库*.a的编译和使用 创建.a库文件和.o库文件: [yufei@localhost perl_c2]$ pwd /home/yufei/perl_c2 [yufei@localhost perl_c2]$ cat mylib.c #include <stdio.h> #include <string.h> void hello(){        printf("success call from perl to c library\n"); } [yufei@localhost perl_c2]$ cat mylib.h extern void hello(); [yufei@localhost perl_c2]$ gcc -c mylib.c [yufei@localhost perl_c2]$ dir mylib.c  mylib.h  mylib.o [yufei@localhost perl_c2]$ ar -r mylib.a mylib.o ar: 正在创建 mylib.a [yufei@localhost perl_c2]$ dir mylib.a  mylib.c mylib.h  mylib.o

*.a的使用方法

最简单的是直接把.a当成一个普通源代码编译进来.  gcc   main.cpp   ./lib/libInfo.a   -o   exec

动态链接库*.so的编译与使用- - 动态库*.so在linux下用c和c++编程时经常会碰到,这里做个笔记,也为其它正为动态库链接库而苦恼的兄弟们提供一点帮助。 1、动态库的编译 下面通过一个例子来介绍如何生成一个动态库。这里有一个头文件:so_test.h,三个.c文件:test_a.c、test_b.c、test_c.c,我们将这几个文件编译成一个动态库:libtest.so。 so_test.h: #include <stdio.h> #include <stdlib.h> void test_a(); void test_b(); void test_c(); test_a.c: #include "so_test.h" void test_a() {     printf("this is intest_a...\n"); } test_b.c: #include "so_test.h" void test_b() {     printf("this is intest_b...\n"); } test_c.c: #include "so_test.h" void test_c() {     printf("this is intest_c...\n"); } 将这几个文件编译成一个动态库:libtest.so $ gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so 2、动态库的链接 在1、中,我们已经成功生成了一个自己的动态链接库libtest.so,下面我们通过一个程序来调用这个库里的函数。程序的源文件为:test.c。 test.c: #include "so_test.h" int main() {     test_a();     test_b();     test_c();     return 0; } l       将test.c与动态库libtest.so链接生成执行文件test: $ gcc test.c -L. -l test -o test l       测试是否动态连接,如果列出libtest.so,那么应该是连接正常了 $ ldd test l       执行test,可以看到它是如何调用动态库中的函数的。

总结: 1、共享库特别适合多个程序共享代码,升级程序部分功能模块,实现程序“插件”功能的情况; 而静态库是一劳永逸,编译后不需要带一堆库文件跑,而且不管放置到哪里都可正常运行。 2、当搜索的库文件目录下同时存在该库的静态版本和共享版本时,链接器优先使用共享版本.so,此时你可以使用-static链接选项指定链接静态版本.a。 3、动态库可以导出两个特殊的函数:_init和_fini,前者在动态库被加载后调用,后者在动态库被卸载前调用, 我们可以使用这两个函数做些特别的工作。需要注意的是:在定义这两个函数后编译时,需要使用 -nostartfiles选项,否则编译器报重复定义错误。 4、ldd命令用来查看程序所依赖的共享库,同时也方便我们判断共享库是否被找到;    nm命令查看obj文件(.so也是一个obj)中的标识(函数、变量)。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏.Net、.Net Core 、Docker

通俗易懂设计模式解析——迭代器模式

  今天我们一起看看行为模式中的迭代器模式,迭代是重复反馈过程的活动,其目的通常是为了接近并到达所需的目标或结果。在系统开发中简单说可以理解成遍历。这种模式用于...

9710
来自专栏AINLP

Awesome-Chinese-NLP:中文自然语言处理相关资料

推荐Github上一个很棒的中文自然语言处理相关资料的Awesome资源:Awesome-Chinese-NLP ,Github链接地址,点击文末"阅读原文"可...

24000
来自专栏WebJ2EE

Spring周边:StringTokenizer

JDK 已经不建议在新代码中使用 StringTokenizer 了,建议使用正则表达式功能替换;

10800
来自专栏IT那个小笔记

Spring-JDBC

Spring提供了很多的模板用于简化开发,有基础的JDBC模板相当于DBUtils,使用Hibernate也有简化使用Hibernate的模板

8400
来自专栏FreeBuf

Adwind家族恶意软件

2012年初,开发人员开始销售Adwind家族的第一个基于Java的远程访问工具(RAT),称为“Frutas”。在随后的几年里它被改写了至少七次。它的其他名字...

9600
来自专栏Java架构师进阶

架构师面试集锦之JVM面试题

Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。 Java被设计成允许应用程序可以运行在任意的...

14500
来自专栏Java架构

JAVA程序员备战跳槽季,准备面试必备的技术大纲,请查收

怎么来体现你的技术实力?我总的分为:技术深度和技术广度这两方面。技术广度通俗的讲,就是你熟悉该技术点的使用以及基本原理。一般面试官在面试首轮会问很多技术点,来考...

13200
来自专栏贺贺的前端工程师之路

Swagger规范 之 出错点

第一天使用的时候我就发现了它确实易懂,直接写就OK。但是在编写API文档的时候,还是遇到了几个不大不小的坑,记录下来,分享一下,其实是深怕自己过几天就忘了!O(...

8200
来自专栏彤哥读源码

死磕 java线程系列之线程模型

在Java中,我们平时所说的并发编程、多线程、共享资源等概念都是与线程相关的,这里所说的线程实际上应该叫作“用户线程”,而对应到操作系统,还有另外一种线程叫作“...

10100
来自专栏程序通事

协作,才能更好的中断线程

除了 InterruptedException 中断异常,另外还有三个中断相关的方法,三个方法都与线程相关。

8000

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励