一、内存管理
brk/sbrk
维护一个位置,brk/sbrk改变这个位置
brk改变绝对位置
sbrk改变相对位置
a.映射虚拟内存
没有任何额外维护数据的内存分配
mmap分配 unmap 释放
1.函数说明
void * mmap(
void *start,//指定映射的虚拟地址 0 由系统指定开始位置
size_t length,//映射空间大小
int prot,// 映射权限 PROT_NONE PROT_READ PROT_WAITE
int flags,//映射方式
int fd,//文件描述符号
offset_t off);文件中的映射开始位置
内存对齐 位段(网络编程);
总结
使用内存的方法
智能指针 指针池
STL
new C++
malloc() 适合小而多的数据申请
brk/sbrk,同类型的大块数据,根据需要动态移动指针
mmap/munmap()控制内存访问(使用文件映射),控制内存的共享)
二、编程工具与动态库
1.GCC
-o
-O - O0 O1 O2 -O3 编译优化
默认
O0
O1
O2
O3
-g -g0 -g1 -g2 -g3 产生调试信息
-W all
-Wall 显示所有警告
-Werror 把所有警告当错误
-w 关闭警告
-c 只编译不连接
-D 在命令行定义宏
定义宏的二种方式:在代码中定义宏,在命令行定义宏
.o目标文件
-E 预编译
-x 指定编译的语言类型
none 根据扩展名,自动判定
-std=c89 标准
=c99
restrict 对函数参数指针使用,类型register 优化
指定输出文件名 -o
.c c程序
.cpp C++程序
.CC C++程序
.h 头文件
.hpp C++头文件
.o 目标文件
.a 归档文件 静态库
.so 动态库
.i 预编译文件
.s 汇编文件
三、静态库的编译
1.编译过程(*.a chieve 归档)
1.1编译成目标文件
-static 可选
1.2 归档成静态库
ar 工具
ar -r 静态库文件 被归档的文件
-t
-p 查看归档文件 nm也可查看,查看的形式不一样
nm工具(查看函数符号表)
nm 静态库或者动态库或者目标文件或者执行文件
1.3 使用静态库
gcc 代码 静态库
使用静态库完成如下程序:
输入一个菱形半径,打印菱形
输入整数封装成TOTool
菱形的打印封装成Graphics 做成图开库的形式
步骤:
1.实现输入
2.实现菱形
3编译静态库
4调用静态库
ar -r 静态库文件
nm工具
总结,库是函数等代码封装的二进制已经编译的归档文件
ar归档工具
优点:
容易组织代码,易于复用,保护代码版权
静态库的含义:编译好的程序运行的时候它不依赖库。库作为程序的一部分编译连接。本质:就是目标文件的集合(归档)。
-static 可选
2.库的规范与约定
库命名规则:
静态 lib+库名.a.主版本号.副版本号.批号
库的使用规则
-l 库名
-L 库所在目录 -L.当前目录 自动搜索前缀lib
四、动态库的编译(共享库)
1.动态库是可以执行,静态库不能执行,但动态库没有main,不能独立执行,动态库不会连接成程序的一部分,
程序执行的时候必须需要动态库文件存在。
2.工具,ldd 查看程序需要调用的库 仅对可执行文件有效elf格式 readelf -h查看ELF文件头信息 windows 下pe格式
nm查看库中的函数符号
动态库的编译
3.编译
-c -fpic-f 指定文件格式 format pic (position independence code位置无关代码)
4.连接
-shared
使用动态库
gcc 代码 动态库名
gcc 代码 -l 库名 -L动态库所在路径
标准命名规则:
lib库名.so
lib库名.a
-l 库名 -L 库所在路径
GCC 编译过程: -E -c -S 自动调用连接器和连接参数
连接器 ld
执行程序加载动态库过程
1.找到动态库
2.加载动态库到内存 系统完成
3.映射到用户的内存空间系统完成
系统对动态库查找规则
/lib
/usr/lib
到环境变量LD_LIBRARY_PATH指定路径中查找
依次查找
linux中设置环境变量export LD_LIBRARY_PATH=. :分割 ..上极路径 ~主路径 .当前路径
仅对当前程序有效
linux缓冲机制:把/lib /usr/lib LD_LIBRARY_PATH 加载到缓冲中
/sbin/ldconfig 查看所有库的缓冲
/sbin/ldconfig -v 刷新缓冲中so的搜索路径
动态库加载的原理
动态库中函数的查找已经封装成库libdl.so dlfcn.h
dlopen 打开一个动态库
dlsym 在打开的动态库中找一个函数
dlclose 关闭动态库
dlerror 返回错误
总结:
编译连接动态库
使用动态库
配置让我们程序调用动态库
掌握ar,nm,ldd,lddconfig工具的使用
综合应用:
输入二个数,计算二个数的和
要求:输入与计算二个数的和封装成动态库的调用
为什么连接时需要指定动态库及目录
连接器需要确定函数在动态库中的位置
五、工具make的使用与makefile脚本
make 编译脚本 makefile
make -f 脚本文件 目标
脚本文件
1.文件文件
2.基本构成语法
基本单位目标target
目标名:依赖目标
\tab+目标指令
目标划分:默认规则
a,不指定目标,执行第一个目标
b.不指定make文件,默认文件是Makefile
makefile优先于Makefile 不存在认为是最新的 把目标当做文件处理
目标调用规则
make执行目标,搜索与目标相同的文件,如果文件存在则判定日期。
日期最新则停止编译,输出提示
日期不是最新,则执行
比较:当前目标与依赖目标 无依赖则目标是最新
建议:每个编译结果做为一个目标,并且把编译结果作为目标名
clean目标,主要用于清空
潜规则:.C目标与.O目标 先查找.o目标,目标如果不存在,就把.o替换成.c
如果.c存在,实施潜规则:直接调用GCC把.c执行为.o
变量:变量名=值
使用变量$(变量名) ${变量名}
伪目标:
不把目标作为文件处理的目标称为伪目标
声明伪目标 .PHONY:+伪目标
1make的配置
2make变量的操作函数
3.多make文件使用
补充知识:环境变量
1.使用main参数
int main(int args,char **argv,char **arge)arge
{
}
命令行参数argv与环境行arge都是字符串数组。
约定最后一个字符串是null/0
2.使用外部变量 extern char **environ 头文件unistd.h
3.修改、获取某个环境变量 getenv/setenv/unsetenv
作业:
1.输入一个整数,打印这个数的goldbach分解
所有大于等于6的偶数都可以分解成两个奇素数之和
要求:
封装成共享库
使用make脚本编译
2.已知一个字符串“tom jack rose”,写一个程序,统计单词个数,并且打印每个单词。
使用共享库封装
使用make脚本
3.输出菜单,选择1打印菱形,选择2打印矩形
选择1,输出菱形4
选择2,输出矩形4*4