[linux内存]linux内存学习——常见问题

1,kmalloc()函数和vmalloc()函数的区别:

kmalloc()函数分配的内存是物理上连续的,而Vmalloc()函数分配的内存仅仅是虚拟地址连续的,正常内核编程通常使用kmalloc(),这主要是处于性能的考虑,因为vmalloc()将物理不连续的页转换为虚拟地址空间上连续的页,必须专门建立页表项,vmalloc()仅仅在当需要使用大块的内存的时候才会使用,典型的如模块被动态插入内核的时候。另外很多硬件设备需要的是物理地址连续的页,因为很多硬件设备存在于内存管理单元(MMU)之外。另外vmalloc()函数可能睡眠,不能在中端上下文使用,而kmalloc加GFP_ATOMIC可以保证用在不能睡眠的地方。

如果希望代码在不同的平台有很好可移植性,则不应该分配大于128K的内存。

kmalloc对应于kfree,分配的内存处于3GB~high_memory之间,这段内核空间与物理内存的映射一一对应,可以分配连续的物理内存; vmalloc对应于vfree,分配的内存在VMALLOC_START~4GB之间,分配连续的虚拟内存,但是物理上不一定连续,vmalloc()分配的对应于高端内存~


2,如何防止频繁的malloc() free()操作造成的内存碎片

答:使用内存池技术。

内存池技术首先会分配一大块内存给程序,当程序需要分配内存的时候从内存池中去获得,而且不需要去释放内存,当内存池不在用的时候释放整个内存即可,只分配,不释放,大大减少了时间。

如何构建内存池


3,内核空间是否可以访问用户空间的内存

答:可以,比如copy_to_user()和copy_from_user()两个函数,

unsigned long copy_to_user(void __user *to,const void *from,unsigned long count)

其中的参数 to就是代表用户空间指针,内核空间要访问用户空间内容,必须要用以上接口,因为在 Linux 中,用户内存和内核内存是独立的,在各自的地址空间实现,以上函数在实现的时候会做内存转换和用户空间地址的检查。copy_from_user的实现


4,使用malloc()会造成内存碎片的原因以及malloc()函数的实现原理

点击打开链接

系统默认当要求分配的内存少于128K的时候则malloc()调用brk()系统调用,当要分配的内存大于128K的时候,则调用mmap()系统调用,brk()系统调用其实就是移动数据段的最高指针_edata指针向高地址移动,由于一个进程只有一个_edata指针,当进程多次调用malloc()函数分配小于128K的内存的时候,比如第一次分配100k,第2次分配20K,第三次分配40k的时候,如果此时要释放第二次分配的20K,但此时_edata的指针位置还是没有变,所以这个20k就变成了内存碎片,如果此时再释放第三次分配的40K的时候,此时brk()的_edata指针位置还是不会变,只有当第一次分配的100k也释放的时候,此时空闲的多余128K,此时才会内存紧缩,此时_edata指针的位置才会变化。

另外即使调用malloc()函数分配使brk()的_edata的指针位置发生变化后,此时只是进程的虚拟地址空间内存被分配,没有分配实际的物理内存,只有当真正的使用的时候才会产生缺页错误,然后系统分配物理内存建立物理内存和虚拟内存的映射关系。

brk()的C语言形式声明如下:

int brk(void *end_data_segment)
mmap()的作用是向操作系统申请一段虚拟地址空间,这块虚拟地址空间可以映射到某个文件,当它不将这个虚拟地址映射到某个文件的时候,我们将这块地址空间称为匿名空间,匿名空间可以拿来作为堆使用。
void *mmap(void *start,size_t length,int port,int flags,int fd,off_t offset)
前两个参数表示要申请空间的起始地址和长度,prot/flags表示设置申请的空间权限以及映射类型,最后两个参数表示映射文件的文件描述符和文件偏移。
堆分配算法:
1,空闲链表
2,位图
3,对象池


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值