系统与内存管理

内存管理的层次划分

STL    智能指针,可以自动分配/释放内存资源  调用C++
C++    new/delete运算符,构造/析构函数     调用标准C
标准C  malloc/calloc/realloc/free         调用POSIX接口
POSIX  brk/sbrk                           调用Linux
Linux  mmap/munmap                        调用kernel
Kernel kmalloc/vmalloc                    调用驱动
驱动   get_free_page 

进程映像

程序就是保存在磁盘上的可执行文件,进程就是被加加载到内存中正在执行的程序。
进程在内存空间中的分布就是进程映像,从低到高依次是:
代码段 text
    可以执行的二进制指令、字面值常量、以及被const保护的原data,bss区的变量,只读,如果强行修改会产生段错误。
全局数据段 data
    初始化的全局变量、静态变量。
静态数据段 bss
    末初始化的全局变量、静态变量。
    进程一旦被加载,该段内存就会被清理为0。
    data和bss合称为全局区或静态区
堆区 heap
    动态内存分配,从低地址向高地址扩展。
    C语言没有管理堆内存的语句,只能通过标准库函数和系统函数对它进行管理。
栈区 stack
    局变量、块变量、函数参数、返回值等都存储在该段内存。
    由系统自动管理,由高到低扩展
命令行参数和环境变量表:指向命令行参数的指针和指向环境变量的指针。

#include <unistd.h>
pid_t getpid(void);
功能:获取当前进程的编号,俗称进程号
cat /proc/进程号/maps 可以查看到当前进程的分布情况。

虚拟内存

1、在32位系统下,每个进程都有0~4G虚拟内存。

2、这些虚拟内存不能直接使用,需要与物理内存建立映射关系后才能使用,否则就会出现段错误。

3、虚拟内存与物理内存的映射由操作系统动态维护。

4、用户永远无法直接使用物理内存,只能使用虚拟内存。

5、4G内存空间分为两部分
    [0~3G] 用户空间 如某栈内存地址为0xbfe95000,约等于3G
    [3G~4G] 内核空间
6、用户空间的代码是不能访问内核空间的代码和数据,但可以通过系统调用进入内核状态,间接的与系统内核交互。

7、每个进程都对应一个用户空间,进程一切换用户空间随之变化,每个进程都有一个独一无二的进程号。

*操作系统的虚拟内存机制有哪些优点?
    安全,防止进程之间的冲突,也可以避免操作系统被破坏

管理内存的API(应用程序接口)

遵循POSIX标准:
brk和sbrk在内部维护一个指令p,指向当前堆内存最一个字节的下一们位置地址。

void *sbrk(intptr_t increment);
功能:根据参数来调整p的位置(p+/-increment),既可以映射虚拟内存也可以取消映射。
返回值:调整前的p的位置。

int brk(void *addr);
功能:根据指针参数修改p的位置(把p设置为addr)。
返回值:成功返回0,失败返回-1。

注意:brk和sbrk都可以单独分配/释放内存,但一般配合使用,sbrk用于分配,brk用于释放。
brk/sbrk只是Linux了为遵循POSIX标准而提供的一套内存映射接口,但它实际上调用的是mmap/munmap。

Linux系统的内存管理:
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
功能:让用户空间的虚拟地址与物理地址建立映射。
addr:映射内存的首地址,如果是NULL则操作系统自动计算。

length:要映射的字节数。

prot:映射的内存权限
    PROT_EXEC  执行权限
    PROT_READ  读权限
    PROT_WRITE 写权限
    PROT_NONE  无权限
    
flags:
    MAP_SHARED 共享映射,映射的内容对其它进程是可见的。
    MAP_PRIVATE 私有映射,映射的内容对其它进程不可见的
    MAP_DENYWRITE 拒绝其它文件写入操作
    MAP_ANON 映射的是内存而非文件
    
fd:文件描述符,类似于文件指针FILE

offset:映射文件时使用到的偏移值

返回值:映射成功后的虚拟内存地址,如果失败返回值为0xffffffff
    
int munmap(void *addr, size_t length);
功能:取消映射
addr:映射内存的首地址
length:内存的字节数
返回值:成功返回0,失败返回-1。

注意:系统的内存映射是以页为单位的(4096byte)

系统调用

1、UNIX/Linux大分部的系统功能是通过系统调用实现的

2、这些系统调用被封装成了C函数的形式,但它们并不是真正的函数。

3、当程序员所编写的代码使用系统调用时,此时会与内核进行交互(发消息),
   借助软中断进入内核态,这是一种中断机制而不是函数调用。

4、标准库函数大部分工作在用户态,部分函数会使用系统调用进入内核态(fopen/malloc)。
   可以使用 time 可执行文件名 统计程序的运行时间:
real    0m0.002s 总执行时间
user    0m0.000s 用户态执行时间
sys     0m0.000s 内核态执行时间
strace 可执行文件名 路径函数的调用过程

频繁切换内核态和用户态也会消耗时间,但是不会显示在real,user,sys中
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值