- 论坛徽章:
- 0
|
帮忙看看这句话怎么理解( from man page of sbrk )
在UNIX/LINUX中,程序运行时动态内存以堆的方式来分配。
对程序而言,它使用的动态内存地址是虚拟内存,
代码用内存和数据用内存,一个从上往下,一个从下往上增长。
在LINUX,X86中,可用虚拟内存为0x00000000--0xffffffff;
对每一个进程都是一个独立的4GB空间。
但前面的1GB是内核用的,后面某一个位置才是程序运行时动态内存堆
的开始地址,你用多少它向上增多少。
比如语句 malloc(1024);
首先虚拟内存向上增长1024;//LINUX,kernel中do_brk();
然后系统使用mmap(),为这虚拟内存映射物理内存。
虚拟内存对物理内存的切入切出是另外的
理论上十分高深的东东,能写数米厚书而实际上就几行代码的东东,
你有时间看看linux内核代码中的mmap()。
说明几点,
程式分配虚拟内存也不是你要一个字节就给你一个字节,
而是你要一个字节给你一个页面,因为映射物理内存时只能以页为单位。
你要另一个字节时,它在这个页面的剩余空间给你。
注意大部份UNIX虚拟内存的使用是只增不减的。
- malloc(32 * 1024) --->;sbrk += 32 * 1024
- free() --->;sbrk 不减少。
- 但如如果再来一次
- malloc(32 * 1024) ---->;sbrk 也不增,使用原有空间.
复制代码
但对于LINUX来说它是要以内存的最大数收缩的;
- a = malloc(32 * 1024) -->;sbrk += 32 * 1024
- b = malloc(32 * 1024) -->;sbrk += 32 * 1024
- if(****){
- free(b); --->;sbrk -= 32 * 1024;
- }
- else{
- free(a); --->;sbrk 不减少。只是多了个空洞.
- }
复制代码
- /* linux kernel code */
- brk()
- /*
- * sys_brk() for the most part doesn't need the global kernel
- * lock, except when an application is doing something nasty
- * like trying to un-brk an area that has already been mapped
- * to a regular file. in this case, the unmapping will need
- * to invoke file system routines that need the global lock.
- */
- asmlinkage unsigned long sys_brk(unsigned long brk)
- {
- unsigned long rlim, retval;
- unsigned long newbrk, oldbrk;
- struct mm_struct *mm = current->;mm;
- down_write(&mm->;mmap_sem);
- if (brk < mm->;end_code)
- goto out;
- newbrk = PAGE_ALIGN(brk);
- oldbrk = PAGE_ALIGN(mm->;brk);
- if (oldbrk == newbrk)
- goto set_brk;
- /******虚拟内存在这里收缩******/
- /* Always allow shrinking brk. */
- if (brk <= mm->;brk) {
- if (!do_munmap(mm, newbrk, oldbrk-newbrk))
- goto set_brk;
- goto out;
- }
- /* Check against rlimit.. */
- rlim = current->;rlim[RLIMIT_DATA].rlim_cur;
- if (rlim < RLIM_INFINITY && brk - mm->;start_data >; rlim)
- goto out;
- /* Check against existing mmap mappings. */
- if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE))
- goto out;
- /* Check if we have enough memory.. */
- if (!vm_enough_memory((newbrk-oldbrk) >;>; PAGE_SHIFT))
- goto out;
- /* Ok, looks good - let it rip. */
- if (do_brk(oldbrk, newbrk-oldbrk) != oldbrk)
- goto out;
- set_brk:
- mm->;brk = brk;
- out:
- retval = mm->;brk; /****这就是返回值*****/
- up_write(&mm->;mmap_sem);
- return retval;
- }
复制代码
在LINUX中sbrk(0)能返回比较精确的虚拟内存使用情况,
在SOLARIS/HP中sbrk(0)返回以页为单位的虚拟内存使用情况。
这样我们就可以用sbrk来得到程式当前使用内存情况。
我时常使用sbrk(0)来返回我的程式当前使用了多少内存。
main(){
int start,end;
start = sbrk(0);
....
malloc(***);
....
end = sbrk(0);
printf("hello I used %d vmemory",end - start);
}
打字打得累死好像还是没有说明白sbrk,没时间打了。
综上所述,我把楼的的那句话
Calling sbrk with an increment of 0 can be used to find the current location of the program break
理解为使用sbrk(0)可以返回当前的程序所有使用的虚拟内存 达到/越过 了的地址。
break = 超过;超越 |
|