回顾:
brk/sbrk
int brk(void *);
void* sbrk(int);
维护一个位置.brk/sbrk改变这个位置
brk改变绝对位置
sbrk相对改变位置;
补充:全新的类型.
永远记住: C的基本类型只有:整数(1字节(bool),2字节(char),4字节(int,int*)),小数(4字节,8字节)
unsigned signed
所有的全新类型都是使用typedef重新定义.
新的类型的C的原型.
类型重定义的好处:
1.维护方便
2.移植
3.容易理解
一. 映射虚拟内存
没有任何额外的维护数据的内存分配
mmap(分配)/umap(释放)
1.函数说明
void * mmap(void *start,//指定映射的虚拟地址 0 由系统指定开始位置
size_t length,//映射空间大小 pagesize倍数
int prot , //映射权限 PROT_NULL PROT_READ PROT_WRITE PROT_EXEC
int flags,//映射方式
int fd,//文件描述符号
offset_t off );//文件映射的开始位置
映射方式:
内存映射:匿名映射.
文件映射:映射到某个文件.只有文件映射时最后两个参数才有效.
MAP_ANONYMOUS 内存映射方式
MAP_SHARED MAP_PRIVATE(二选一)
2.案例
3.总结
选择什么样的内存管理方法?
STL
new
malloc(小而多数据)
brk/sbrk(同类型的大块数据,动态移动指针)
mmap/munmap(控制内存访问/使用文件映射)
4.应用
二.编译工具与动态库
1.gcc
-o 文件名 重命名编译后的文件
-O0 -O1 -O2 -O3 编译优化
-g -g0 -g1 -g2 -g3
-Wall 显示所有警告
-Werror 把所有警告当成错误
-w 关闭警告
-c 只编译不链接
-E 预编译
-S 汇编文件
-D 在命令行定义宏.
在代码上定义宏
在命令行定义宏
-x 指定编译的的语言类型
assemble
c
c++
gcc -x assemble test.s
gcc -x c test.c
gcc -x c++ test.cpp
-std =c89
-std =c99 主函数返回int
int add(int * restrict a,int * restrict b);
编译过程: -E -S -c
ld map.o 链接
链接器一般都是自动调用连接器
补充:
.c
.cpp
.CC
.h
.hpp
.o
.a
.so
.i 预编译文件
.s 汇编文件
2.make
3.gdb
4.其他工具
5.共享库
三.静态库的编译
1.编译过程(*.a achieve)
1.1 编译成目标文件
-static 可选
gcc -c -static 代码文件
1.2 归档为静态库
ar工具
ar -r
-t
-p
-x
-m
-q
ar -r 静态库文件 被归档的文件
ar -r ku.a ku1.o ku2.o
ar -t ku.a 查看库内文件
nm工具(查看函数符号表)
nm 静态库或者动态库或者目标文件或者执行文件
nm ku.a 查看归档文件
1.3 使用静态库
gcc 代码 静态库
gcc callku.c ku.a -o mainT
./mainT
使用静态库完成如下程序:
输入一个菱形半径,打印菱形.
输入整数封装成IOTool
菱形的打印封装成Graphics
计划:
1.实现输入
2.实现菱形
3.编译静态库
4.调用静态库
总结:
1.什么是库?
函数等代码封装的二进制已经编译的归档文件
2.ar归档工具
3.采用库的方式来管理代码优点:
容易组织代码
服用
保护代码版权
4.静态库的静态的含义:
1.编译好的程序运行的时候不依赖库.库作为程序的一部分
编译连接
5.静态库本质:
目标文件集合(归档)
6 -static 可选
------------------------------------------------
gcc -c -static ku1.c
gcc -c -static ku2.c
ar -r ku.a ku1.o ku2.o
gcc callku.c ku.a -o main
./main
------------------------------------------------
2.库的规范与约定
库命名规则:
lib.库名.a.主版本号.副版本号.主批次号
lib库名.a
库使用规则
-l 库名
-L 库所在目录
------------------------------------------------
gcc -c -static ku1.c
gcc -c -static ku2.c
ar -r libdemo.a ku1.o ku2.o
gcc callku.c -o main -ldemo -L.
./main
------------------------------------------------
四.动态库的编译
1.什么是动态库(共享库)
动态库是可以执行,静态库不能执行.
但动态库没有main,不能独立执行
动态库不会链接成程序的一部分.
程序执行的时候,必须需要动态库
2.工具
ldd 查看程序需要调用的动态库
ldd main
ldd只能查看可执行文件.
windows可执行文件格式 PE
linux可执行文件格式ELF
readelf -h main 查看执行文件头
nm 查看库中的函数符号
3.动态库的编译
1.编译
-c -f pic(可选) position indepe code
2.链接
-shared
----------------------------------------------------
gcc -c -f pic ku1.c
gcc -c -f pic ku2.c
gcc -shared -o libdemo.so ku1.o ku2.o
----------------------------------------------------
4.使用动态库
gcc 代码 动态库文件名
gcc 代码 -o main -l demo -L . // .表示当前目录
问题:
4.1 执行程序怎么加载动态库
4.2 动态库没有作为执行程序的一部分,为什么连接器需要确定函数在
在动态库中的位置.
动态库的加载:
1.找到动态库
2.加载动态库到内存空间
3.映射到用户的内存空间
动态库的查找规则:
/lib
/user/lib
到环境变量LD_LIBRARY_PATH
export LD_LIBRARY_PATH=.:~:..:~username
缓冲机制:
把/lib:/usr/lib:LD_LIBRARY_PATH加载到缓冲区
/sbin/ldconfig -v 刷新缓冲区中的搜索数据
动态库的加载原理
-------------------------------
#include<dlfcn.h>
main()
{
void * handle=dlopen("./libdemo4.so",RTLD_LAZY);
void (*fun)(int) = dlsym(handle,"fun_name");
fun(5);
dlclose(handle);
}
gcc dldemo.c -o main -l dl //加载dl库,不用加载libdemo4.so
-------------------------------
动态库中函数的查找已经封装成库libdl.so
dlopen 打开一个动态库
dlsym 在打开的动态库中查找一个函数
dlclose 关闭动态库
dlerror 返回错误
总结:
1.编译连接动态库
2.使用动态库
3.怎么配置让程序调用动态库
4.掌握某些工具的使用 nm ldd lddconfig
strip 删除多余信息
strip libdemo.so
objdump
六.工具make的使用与makefile脚本
背景:
make 编译脚本解释
编译脚本Makefile
make -f 脚本文件 目标
脚本文件
1.文本文件
2.基本构成语法:
基本单位目标target:
目标名:依赖目标
目标名:依赖目标
\t;
-----------------------------------------//demo.mk
demo:
@gcc iotool.c -c -f pic 空格只能用tab
gcc graphic.c -c -f pic
gcc iotool.0 graphic.c -shared -o libdemo.so
gcc main -ldemo -o main -L. //直接编译链接一步到位
----------------------------------------
teminnal运行
make -f demo.mk demo
-----------------------------------------
本文介绍了内存管理方法如brk/sbrk、mmap/munmap的不同应用场景,并详细讲解了GCC编译器的使用技巧及选项。同时,探讨了静态库与动态库的创建、使用方法及其优缺点。
9501

被折叠的 条评论
为什么被折叠?



