DAY02AM
回顾:
brk/sbrk
intbrk(void *p)
void*sbrk(int);
补充:全新的类型。
永远记住:C的基本类型就:整数(1.char2.short 4.int)、小数(4.float 8.double)
所有全新类型都是使用typedef重新定义的。
新的类型的C的原型。
类型重定义的好处:1.维护方便 2.移植 3.容易理解
维护一个位置。brk/sbrk改变这个位置
brk改变绝对位置
*sbrk相对改变位置
一、映射虚拟内存
没有任何额外维护数据的内存分配。
mmap(分配)/ munmap(释放)
1.函数说明
manmmap
void*mmap(
void*start, //指定映射的虚拟地址 ,0由系统指定开始位置
size_tlength, //映射空间大小,pagesize倍数
intprot, //映射的权限 PROT_NONE PROT_READ PROT_WRITE PROT_EXEC
intfalgs, //映射的方式
intfd, //文件描述符
off_t_toffset); //文件中的映射开始位置,pagesize倍数
映射方式:
内存映射:(匿名映射)
文件映射:映射到文件。
只有文件映射最后两个参数才有效,否则无效。
MAP_ANONYMOUS//内存映射方式 (选/不选)
MAP_SHAREDMAP_PRIVATE (二选一)
size_tlength //4k*(length/4k +1)
intprot //权限只有三种读\写\执行
off_t_toffset //必须是4k的整倍数
intmunmap(void *start, size_t length);
2.案例
3.总结
选择什么样的内存管理方法?
智能指针(指针池) --在ObjectC中
STL
new
malloc(小而多数据)
brk/sbrk(同类型的大块数据,动态移动指针)
mmap/munmap(1.控制内存访问 2.使用文件映射 3控制内存共享(父子进程之间))
C++用的是 STL, new()
最方便的是 STL new
效率最高的、数组最快的是brk/sbrk 和 mmap/munmap
4.应用
二、编程工具与动态库
1.gcc
-o输出文件名
-O-O0 -O1 -O2 -O3编译优化
-g-g0 -g1 -g2 -g3产生调试信息
-W-all error //把空格省掉就是 -Wall显示所有警告 -Werror把警告当作错误
-o关闭所有警告
-c只编译不连接
-E预编译 //gcc map.c -E -o -map.i
-S汇编 //gcc map.c -S //生成map.s文件
-D在命令行定义宏
在代码中定义宏
在命令行定义宏
-x指定编译的语言类型 //gcc -x assembler maps.s
c++
c
.S
none自动判定
-std=c89
c99
编译过程 -E -c -S//自动调用连接器
连接器 ld //ld map.s | ld map.o
补充:
.c :C
.cpp:C++
.CC :C++
.h :头文件
.hpp:C++头文件
.o :目标文件
.a
.so :共享目标文件、动态库
.i :预编译文件
.s :汇编文件
产生预编译文件
gccmap.c -E -o map.i
catmap.i
2.其他工具
3.共享库
4.make
5.gdb
三、静态库的编译
1.编译过程(*.aachieve)
1.1.编译成目标文件
-static//可选
gcc-c -static代码文件.c
1.2.归档成静态库
ar工具
ar -r
-t
-p
-x
-m
-q
ar-r静态库文件被归档的名称[列表]
ar-t查看库中含有那几个文件
nm工具(查看函数符号表)
nm静态库、动态库、目标文件、执行文件
1.3.使用静态库
gcc代码静态库
使用静态库完成如下程序:
输入一个菱形半径,打印菱形
输入整数封装成IOTool
菱形的打印封装成Graphics
计划:
1.实现输入
2.实现菱形
3.编译静态库
4.调用静态库
四、动态库的编译
代码map.c |
#include<stdio.h> #include<sys/mman.h> #include<stdlib.h> //NULL #include<stdio.h> int main() { int *p = mmap( NULL, getpagesize(), //返回基本单位 PROT_READ | PROT_WRITE, //如果只有PROT_READ就会返回段错误 MAP_ANONYMOUS | MAP_SHARED, 0,0);
*p = 20; *(p+1) = 30; *(p+2) = 40;
printf("%d\n", p[2]); } |
执行结果: |
PROT_READ,//如果只有PROT_READ就会返回段错误 |
释放内存 munmap函数调用 |
#include<stdio.h> #include<sys/mman.h> #include<stdlib.h> //NULL #include<stdio.h> int main() { int *p = mmap( NULL, getpagesize(), //返回基本单位 PROT_READ | PROT_WRITE, //如果只有PROT_READ就会返回段错误 MAP_ANONYMOUS | MAP_SHARED, 0,0);
*p = 20; *(p+1) = 30; *(p+2) = 40;
printf("%d\n", p[2]);
munmap(p, 4096); } |
编译优化测试
默认情况下产生的文件大小 |
-O0 |
-O1 |
-O2 |
-O3 |
产生调试信息测试
默认情况下产生的文件大小 |
-g0 |
-g1 |
-g2 |
-g3 |
int printf(const char*,...); int add(int * restrict a, int * restrict b) { return (*a) + (*b); }
main() { for(int i = 0; i < 100; i ++) { printf("%d\n", NUM); } } |
-std89 不支持 restrict -std99 支持 restrict |
Ku1.c |
int add(int a, int b) { return a + b; } |
Ku2.c |
int sub(int a, int b) { return a - b; } |
Callku.c |
main() { int r = add(45, 55); int s = sub(100, 45); } |
Gcc callku.c ku1.c ku2.c –ocallku //不用库的方式,库的好处可以减小文件的大小 |
编译成目标文件 |
ar -r 静态库文件被归档的名称[列表] |
ar -t 查看库中含有那几个文件 |
ar -p |
nm工具nm ku.a |
使用静态库 |
Iotool.c |
#include<stdio.h>
int inputInt(const char *info) { int r; printf("%s:", info); scanf("%d",&r); return r; } |
Graphic.c |
#include<stdio.h> void diamond(int r) { int x, y; for(y = 0; y < 2*r; y ++) { for(x = 0; x < 2*r; x ++) { if(y == x + r || y == x -r || y == -x + r || y == -x + 3*r ) { printf("*"); } else { printf(" "); } }
printf("\n"); } } |
T 自己实现的函数 U 外部库引用的函数 |