brk系统调用实现分析

brk(addr)直接修改堆的大小。addr指定current->mm->brk的新值,返回值是线性区新的结束地址,这是一个系统调用。当用户态的进程调用brk()系统调用时,内核执行sys_brk(addr)函数。下面分析这个函数的执行流程:

1:检测addr参数是否位于进程代码段所在的线性区,如果是直接返回,因为堆不能与进程代码段所在的线性区重合。

mm=current->mm;
down_write(&mm->mmap_sem);
if(addr<mm->end_code){
out:
	up_write(&mm->mmap_sem);
	return mm->brk;
}

2:由于brk系统调用作用于一个线性区,它分配和释放完整的页。因此,该函数把addr的值调整为PAGE_SIZE的倍数,然后把调整的结果和内存描述的brk进程比较。

newbrk=(addr+0xfff)&0xfffff000;
oldbrk=(mm->brk+0xfff)&0xfffff000;
if(oldbrk==newbrk)
{
	mm->brk=addr;
	goto out;
}

3:如果进程请求缩小堆,则sys_brk()调用do_munmap()完成这项任务,然后返回

if(addr<=mm->brk)
{
	if(!do_munmap(mm,newbrk,oldbrk-newbrk))
		mm->brk=addr;
	goto out;
}

4:如果进程请求扩大堆,则sys_brk首先检查是否允许进程这么做。如果进程企图分配在其限制范围之外的内存,函数并不多分配内存,只简单返回mm->brk的原有值

rlim=current->signal->rlim[RLIMIT_DATA].rlim_cur;
if(rlim<RLIM_INFINITY & addr - mm->start_data>rlim)
	goto out;

5:然后,函数检查扩大之后的堆是否和进程的其他线性区重叠,如果是,不做任何事情就返回:

if(find_vma_itersection(mm,oldbrk,newbrk+PAGE_SIZE))
	goto out;

6:如果一切都顺利,则调用do_brk()函数。如果返回oldbrk,则分配成功且sys_brk返回addr的值,否则返回旧的mm->brk

if(do_brk(oldbrk,newbrk-oldbrk)==oldbrk)
	mm->brk=addr;
goto out;

do_brk()函数实际上是仅处理匿名线性区的do_mmap()简化版。可以认为它的调用等价于:

do_mmap(NULL,oldbrk,newbrk-oldbrk,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_FIXED|MAP_PRIVATE,0)

当然do_brk()比do_mmap()稍快,因为前者假定线性区不映射磁盘上的文件,从而避免了检查线性区对象的几个字段。在这里就不介绍do_brk()函数了,因后面会写一篇专门介绍重要的do_munmap。

brk系统调用实现分析

时间: 2024-11-02 12:11:08

brk系统调用实现分析的相关文章

Linux中brk()系统调用,sbrk(),mmap(),malloc(),calloc()的异同【转】

转自:http://blog.csdn.net/kobbee9/article/details/7397010 brk和sbrk主要的工作是实现虚拟内存到内存的映射.在GNUC中,内存分配是这样的:       每个进程可访问的虚拟内存空间为3G,但在程序编译时,不可能也没必要为程序分配这么大的空间,只分配并不大的数据段空间,程序中动态分配的空间就是从这一块分配的.如果这块空间不够,malloc函数族(realloc,calloc等)就调用sbrk函数将数据段的下界移动,sbrk函数在内核的管理

linux中mmap系统调用原理分析与实现

参考文章:http://blog.csdn.net/shaoguangleo/article/details/5822110 linux中mmap系统调用原理分析与实现 1.mmap系统调用(功能)      void* mmap ( void * addr , size_t len , int prot , int flags ,int fd , off_t offset )      内存映射函数mmap, 负责把文件内容映射到进程的虚拟内存空间, 通过对这段内存的读取和修改,来实现对文件的

win10系统调用架构分析

1.  操作系统模型 大多数操作系统中,都会把应用程序和内核代码分离运行在不同的模式下.内核模式访问系统数据和硬件,应用程序运行在没有特权的模式下(用户模式),只能使用有限的API,且不能直接访问硬件.当用户模式调用系统服务时,CPU执行一个特殊的指令以切换到内核模式(Ring0),当系统服务调用完成时,操作系统切换回用户模式(Ring3). Windows与大多数UNIX系统类似,驱动程序代码共享内核模式的内存空间,意味着任何系统组件或驱动程序都可能访问其他系统组件的数据.但是,Windows

linux系统调用原理分析

自己想看看别人开发的项目,吸收下经验,然后找到开源中国,有些网上的大牛自己也开发出了开源中国的客户端 在网上看到很多网友说,下载下来安装不了之类的东西,在我这里我带个路,希望对那些朋友有些帮助. https://github.com/jimneylee/JLRubyChina-iPhone   开源中国源码地址 界面如下: 很多的朋友会直接点击Download ZIP,然后下载下来,打开,打开后就直接CocoaPods更新运行如下命令行 $ pod install 下载了其他的sdk下来后,以为

linux内核文件IO的系统调用实现分析(open)

http://blog.chinaunix.net/uid-23969156-id-3086824.html 1.          引言      从事Linux环境工作2年有余,一直懵懵懂懂,1年前拜读了<莱昂氏UNIX源代码分析>一书,感觉自己的学习道路漫漫且修远.最近受chinaunix的精华文帖启发,拟将近来的部分内核调用分析笔记拿出来与各前辈先进共同探讨学习,以壮个人学习之路.      本部分主要讲述的是文件I/O操作的2.6.11内核版本实现,包括了主要的数据结构.宏定义和函数

Pin截获socket系统调用初步分析

Pin截获socket系统调用初步分析 根据为知笔记中上传的Pin tool for tracing system calls,修改代码过滤出socket相关的系统调用,并进行初步的分析.主要有2点: - 过滤socket相关的系统调用 - 分析得到的系统调用参数 过滤socket相关的系统调用 socket编程中与访问网络相关的主要关注socket().accept().然后在PinTool中过滤出这两个系统调用,对他们的参数进行初步的分析.下面先看一下这两个函数: int socket(in

Socket与系统调用深度分析

Socket与系统调用深度分析 可以想象的是,当应用程序调用socket()接口,请求操作系统提供服务时,必然会系统调用,内核根据发起系统调用时传递的系统调用号,判断要执行的程序,若为socket对应的编号,则执行socket对应的中断服务程序.服务程序内部,又根据你要请求的不同服务,来执行不同服务对应的处理程序.当处理结束,执行返回,从中断服务程序到发起中断的int 0x80,再到用户态我们执行的用户程序,层层返回,socket()也就执行完毕了. 本次,我们关心三个问题: 1.应用程序如何如

【Socket系统调用】Socket与系统调用深度分析

Socket与系统调用深度分析 系统调用 在一开始,应用程序是可以直接控制硬件的,这就需要程序员有很高的编程能力,否则一旦程序出了问题,会将整个系统Crash. 在现在的操作系统中,用户程序运行在用户态,而要进行诸如Socket.磁盘I/O这样的一些操作,这需要切换到内核态,再进行进行相应的操作,而这一过程则是系统调用system call.有了操作系统分离了内核和用户态,应用程序就无法直接进行硬件资源的访问,需要经过系统调用来进行. 每次的系统调用,都会从用户态转换到内核态,运行完任务后,回到

[转载]Windows系统调用架构分析—也谈KiFastCallEntry函数地址的获取

原文地址:点击打开链接 为什么要写这篇文章 1.      因为最近在学习<软件调试>这本书,看到书中的某个调试历程中讲了Windows的系统调用的实现机制,其中讲到了从Ring3跳转到Ring0之后直接进入了KiFastCallEntry这个函数. 2.      碰巧前天又在网上看到了一篇老文章介绍xxx安全卫士对Windows系统调用的Hook,主要就是Hook到这个函数 3.      刚刚做完毕业设计,对使用中断来实现系统调用的方式记忆犹新. 以上原因导致我最近眼前总是出现系统调用这