头文件与库文件

概要

在使用C语言和其他语言进行程序设计的时候,需要头文件来提供对常数的定义和对系统及库函数调用的声明

  1. 库文件是一些预先编译好的函数集合,那些函数都是按照可重用原则编写的
  2. 它们通常由一组互相关联的用来完成某项常见工作的函数构成
  3. 比如用来处理屏幕显示情况的函数(ncurses库)和数据库访问例程(dbm库)等

使用库的优点:

  1. 模块化开发
  2. 可重用性
  3. 可维护性

头文件与库文件的位置

/usr/include及其子目录底下的include文件夹 /usr/local/include及其子目录底下的include文件夹 /usr/lib /usr/local/lib /lib

使用外部库【-i选项】

示例

#include <math.h>
#include <stdio.h>

int main()
{
    double ans = pow(2.0,3.0);
    printf("pow(%lf,%lf) = %lf\n",2.0,3.0,ans);

    return 0;
}

编译: gcc -Wall calc.c -o calc -lm

-lm表示要链接libm.so或者libm.a库文件


静态库与共享库

简介

静态库(.a):

  1. 程序在编译链接的时候把库的代码链接到可执行文件中
  2. 程序运行的时候将不再需要静态库,静态库占用磁盘空间较大

共享库(.so/.sa):

  1. 程序在运行的时候才去链接共享库的代码,多个程序可共享使用库的代码
  2. [最近的Linux[CentOS 6.4]版本在/usr以及/lib目录下已经找不到.a文件的踪影了]

共享库的优点:

  1. 一个与共享库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码
  2. 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该共享库中复制到内存中,这个过程称为动态链接(dynamic linking)
  3. 共享库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。
  4. 操作系统采用虚拟内存机制允许物理内存中的一份共享库被要用到该库的所有进程共用,节省了内存和磁盘空间。

生成静态库

可以简单的认为将多个.o文件打包到一起,就生成了静态库

  • gcc -c hello_fn.c

gcc -Wall -c hello_fn.c -o hello_fn.o

  • ar rcs libhello.a hello_fn.o search.o

ar是gnu归档工具,rcs表示(replace and create),相当于将将.o文件打包成为.a文件,并且.o文件可以有多个

  • gcc -Wall main.c libhello.a -o main

将各个模块编译,链接生成可执行文件【方式一】

  • gcc -Wall -L. main.c -o main -lhello

-L.表示在当前目录搜索库文件,-lhello[省略的lib],此时即使删除静态库libhello.a也可运行main文件【方式二】

库的搜索路径

  • 从左到右搜索-I -L指定的目录
  • 由环境变量指定的目录

可以定义

  1. C_INCLUDE_PATH/CPP_INCLUDE_PATH(头文件搜索路径)
  2. LIBRARY_PATH(库文件搜索路径) 保存在~/.bash_profile中,另在Debian系统中,也可以将这些定义存放在~/.bashrc

  3. 由系统指定的目录:/usr/include,/usr/lib

生成共享库

gcc -shared -fPIC hello_fn.o -o hello_fn.so

说明:

  1. shared表示生成共享库
  2. -fPIC表示生成位置无关码(Position Independent Code)
  3. 库的命名规则:libXXX.so[.版本号]

使用共享库

  • gcc main.o -o main –L. -lhello

该命令与使用静态库的命令相同,但是,在共享库与静态库共存的情况下,优先使用共享库

l:链接共享库,只要库名即可(去掉lib以及版本号) L:链接库所在的路径.

  • 运行共享库

  • 拷贝.so文件到系统共享库路径下,一般指/usr/lib

  • ~/.bash_profile文件中,配置LD_LIBRARY_PATH变量 export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH source ~/.bash_profile
  • 配置/etc/ld.so.conf,配置完成后调用ldconfig更新ld.so.cache

  • ldd命令:用于查看程序运行时需要加载的共享库