一、内存管理技术
1.1 内存管理的相关函数
(1)brk()(问题:电脑无法完全删除分配的动态内存)
#include <unistd.h>
int brk(void *addr);
-
功能:
-
主要用于调整动态内存的大小,具体调整方式如下:
- 当addr > 原来的末尾地址时,表示申请动态内存;
- 当addr = 原来的末尾地址时,表示动态内存不变;
- 当addr < 原来的末尾地址时,表示释放动态内存;
注意:
虽然brk()既能申请动态内存,又能释放动态内存,但是释放动态内存更加方便,所以一般与sbrk()搭配使用,sbrk()专门用于申请,brk()专门用于释放;
(2)sbrk()
#include <unistd.h>
void* sbrk (intptr_t increment); //intptr_t = long int
-
功能:
- 主要用于调整动态内存的大小,具体调整方式如下:
- 当increment > 0时分配虚拟内存;(
increment
:虚拟内存增量,单位:字节) - 当increment < 0时释放虚拟内存;
- 当increment = 0时为当前堆尾指针;
练习:
使用sbrk函数申请内存,使用brk函数释放内存,首先申请一个int类型大小的动态内存,存放数据66,再申请一个double类型大小的动态内存,存放数据3.14,再申请10个字节大小的字符串空间,存放数据”hello“,打印相关数据,最后释放所有动态内存。
(3)mmap()
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); //off_t = long int
-
功能:
- 主要用于建立文件/设备到虚拟地址的映射; 参数:
-
第一个参数:建立映射的起始地址;(NULL表示系统内核指定)
第二个参数:建立映射的长度;
第三个参数:映射的访问权限;
PROT_EXEC - - - - 可执行
PROT_READ - - - - 可读
PROT_WRITE - - - 可写
PROT_NONE - - – 不可访问
第四个参数:具体的操作标志;
MAP_SHARED —- 映射区的数据直接反映到文件中
MAP_PRIVATE —- 映射区的数据不会反映到文件中
第五个参数:文件描述符;
第六个参数:偏移量;
返回值:
- 成功返回映射区的首地址,失败返回MAP_FAILED ((void*)-1)
(4)munmap函数
#include <sys/mman.h>
int munmap(void *addr, size_t length);
-
功能:
- 主要用于解除参数指定的映射; 参数:
-
第一个参数:映射区的首地址;
第二个参数:映射区的大小;
1.2 内存管理函数的层次关系
C++ ’—- 使用new()申请,delete()释放;
|
标准C语言 —- 使用malloc()申请,free()释放;[上层]
|
POSIX标准 —- 使用sbrk()申请,brk()释放;
|
linux系列:ubuntu fedoral redhat debian …
|
操作系统 —- 使用mmap()建立映射,munmap()解除映射;[底层]
(1)对于malloc() / free()
-
注意:
-
1)malloc/free成对出现;
2)未执行malloc,进程中没有堆区;
3)执行malloc后,系统会最少给当前进程分配33page;
4)每次malloc时,如果申请4个字节,实则耗费了更多的字节,其中多出 来的字节用于存储malloc的附加信息;在使用过程中不能越界,否则可能 造成未知后果。
(2)mmap:
1)动态申请内存;
2)映射文件:映射普通文件、映射设备(显存设备)
-
static的作用:
-
声明一个静态的变量;(数据段)
1)修饰局部变量;
2)修饰全局变量;(本模块可见)
3)修饰函数;(本模块可见)
const的作用:
-
常量(的)指针:int const *a;
指针常量:int * const a;
测试:
-
int a[10][20];
&a + 1 = a的地址+10*20*4的字节
二、文件的管理
2.1 基本概念
在linux系统中,几乎所有的一切都可以看作文件,包括目录、输入输出设备等。
/dev/null —- 空设备文件
-
如:
-
$ echo hello
=>表示打印hello字符串
$ echo hello > a.txt
=>表示将hello字符串插入到a.txt文件中,插入成功
$ cat /dev/null > a.txt
=>表示清空文件中的内容
2.2 常用基本操作函数(重点)
标C中函数:
fopen() / fclose() / fread() / fwrite() / fseek();
UC中函数:
open() / close() / read() / write() / lseek();
(1)open()
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);
-
功能:
- 主要用于打开/创建一个文件; 参数:
-
第一个参数:字符串形式的路径名
第二个参数:具体的操作标志
必须包含以下三个标志中一个:
O_RDONLY - - – 只读
O_WRONLY – – 只写
O_RDWR - - - - - 可读可写
除此之外,还可以按位或以下标志:
O_APPEND —- 以追加的方式打开文件;
O_CREAT - - - - 若文件不存在则创建,若存在则打开;
O_EXCL - - - - – 与O_CREAT搭配使用,若文件不存在则创建,若文件存在则创建失败;
O_TRUNC - - - -若文件存在,则清空文件中的内容;
第三个参数:指定新文件创建时的权限信息;(仅打开已存在的文件时,不需要该参数)
返回值:
- success —- 新的文件描述符,error —- -1; 注意:
-
creat() is equivalent to open() with flags equal to
O_CREAT|O_WRONLY|O_TRUNC
.
(2)close()
#include <unistd.h>
int close(int fd);
功能:
主要用于关闭参数指定的文件描述符,让该文件描述符不再代表任何一个文件,该文件描述符可以被再次使用;
返回值:
success —- 0,error —- -1;
(3)read()
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count); //ssize_t = long int; size_t = long unsigned int
功能:
主要用于从参数指定的文件中读取数据;
参数:
第一个参数:文件描述符;
第二个参数:缓冲区首地址;
第三个参数:期望读取的字节数;
返回值:
success —- 实际读取数据大小,error —- -1
(4)write函数
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
功能:
主要用于将指定的数据写入到指定的文件中;
参数:
第一个参数:文件描述符;
第二个参数:缓冲区首地址;
第三个参数:期望写入的数据大小;
返回值:
success —- 实际写入数据大小,error —- -1
注意:
写入多少字节,则文件读写位置前进多少字节。
练习:
分别使用标C和UC的文件操作函数向文件num.dat和num2.dat写入数据[1~100万],观察程序执行的速度快慢。
测试结果:标C更快0.059s —- 0.949s
扩展:
执行命令:$ ls -l 01brk.c
结果如下:
- r w - r w - r - - 1
文件类型 属主权限 属组权限 其他用户权限 硬链接数
xyq xyq 906 4月 22 15:37 01brk.c
属主名称 属组名称 文件大小 最后一次修改时间 文件名称
注意:
属主 —- 创建者,属组 —- 创建者所在组
其中文件的主要类型有:
- 普通文件
d 目录文件
其中文件的权限主要有:
r 可读 4
w 可写 2
x 可执行 1
- 没有此权限 0
因此:0664 => r w - r w - r - -