Linux系统编程巩固--02

一.静态库

1.为什么需要库

二进制形式目标模块的包
a.o  |
b.o  |----abc.a----库
c.o  |

2.库的类型

1)静态库:扩展名.a,库中所封装的二进制代码,在链接阶段被复制到调用模块中
2)动态库:扩展名.so,库中所封装的二进制代码,在链接阶段并不复制到调用模块中,被嵌入到调用模块中的仅仅是被调用函数在共享库的地址,根据这个地址
动态执行共享库中的代码(windows下.dll)

3.构建静态库

1)编辑源程序: .c/.h
2)编译成目标文件: gcc -c xxx.c ----> xxx.o
3)打包成静态库文件 ar -r libxxx.a xxx.o...

ar [选项] 静态库 目标文件列表
-r:将目标文件插入到静态库中,若已经存在则更新
-q:将目标文件追加到静态库的尾部
-d:将目标文件从静态库中删除
-t:列表显示静态库中目标文件
-x:将静态库展开为目标文件

nm命令:查看目标文件,库文件,可执行文件中的符号列表

4.调用静态库

gcc main.c libmath.a(直接调用法)
gcc main.c -lmath -L.(参数法)
-l:要编译的库名
-L:库的搜索路径
gcc main.c -lmath
export LIBRARY_PATH=$LIBRARY_PATH:.
为了使环境变量持久化
可以把export LIBRARY_PATH=$LIBRARY_PATH:.命令
添加到 ~/.bashrc

       ~/.bash_profile

二.动态库

1.创建动态库

1)编辑源程序 .c/.h
2)编译成目标模块:
    gcc -c -fpic xxx.c ---> xxx.o
        -fpic:小模式,代码量比较小,速度快,只支持一部分平台,如linux
        -fPIC:大模式,代码量比较大,速度慢,所有平台都支持
3)链接成共享库
gcc -shared xxx.o... -o libxxx.so

2.使用动态库

1)静态加载

gcc main.c libmath.so
gcc main.c -lmath -L.
export LIBRARY_PATH = $LIBRARY_PATH:.
gcc main.c -lmath
运行时要保证LD_LIBRARY_PATH环境变量包含动态库所在路径

2)动态加载

#include <dlfcn.h>
A.加载共享库
void *dlopen(
const char *filename,
int flag
);
filename:如果你只给共享库文件名,则通过LD_LIBRARY_PATH环境变量搜索共享库。若给的是共享库的路径,不适用环境变量
flag:
RTLD_LAZY:延迟加载,什么时候使用共享库再实际载入
RTLD_NOW:立即加载
成功返回动态库的句柄,失败返回NULL

B.获取函数地址
void *dlsym(
void *handle,//共享库句柄
const char *symbol//函数名
);
成功返回函数地址,失败返回NULL

C.卸载共享库
int dlclose(
void *handle//共享库的句柄
);
成功返回0,失败返回非0

D.获取错误信息
char *dlerror(void);
返回错误信息的字符串,没有错误返回NULL

gcc 1dyso.c -ldl

三.几个辅助工具

nm:查看目标文件,库文件,可执行文件的符号列表
ldd:查看可执行程序或共享库的动态依赖
strip:通过删除符号表和调试信息,给目标文件,可执行文件,库文件减肥
objdump:对机器指令做反汇编

四.错误处理

1.通过返回值表示错误
    1)返回合法值表示成功,非法值表示失败
    2)返回有效指针表示成功,返回空指针(NULL/0xffffffff)表示失败
    3)返回0表示成功,返回-1表示失败,如果有数据需要返回给调用者,可以通过使用指针形参向其输出
    4)如果一个函数永远不会失败,也没有数据需要提供给调用者,可以没有返回值


2.通过错误代码获取函数失败的原因
#include <errno.h> //extern int errno;
1)通过errno全局变量获取错误原因
2)将errno转换成一个字符串
#include <string.h>
char *strerror(int errnum);
#include <stdio.h>
void perror(const char *s);
printf("%m");
所有的错误代码都非0,errno=0表示无错误
errno是一个全局变量,其值随时有可能发生变化,不安全

五.环境变量

1.环境表

1)每个进程都会收到一张环境表
是一个以NULL指针结尾的字符指针数组
注意:当我们以指针数组作为形参时,通常不传递数组大小,而使数组以空指针结
2)全局变量environ保存了环境表的首地址
3)main函数的第三个参数就是环境表的首地址

2.环境变量的函数

所在库<stdlib.h>
环境变量:<name> = <value>
getenv:通过name获得value
putenv:以<name> = <value>形式设置环境变量,如果name不存在就添加
存在就修改
setenv:根据name设置value,若name已经存在,根据参数决定是否覆盖原value
unsetenv:删除环境变量
clearenv:清空环境变量,environ == NULL


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值