malloc分配内存的实现中brk和mmap的区别

malloc分配内存的实现中brk和mmap的区别,第1张

malloc分配内存的实现中brk和mmap的区别 malloc函数族:
       #include 

       void *malloc(size_t size);
       void free(void *ptr);
       void *calloc(size_t nmemb, size_t size);
       void *realloc(void *ptr, size_t size);
       void *reallocarray(void *ptr, size_t nmemb, size_t size);

malloc:
分配size大小的内存空间,并返回一个指向这片空间的指针ptr。这片空间并为被初始化。若size=0,则返回NULL,或者一个之后能够被正确free的指针。
Linux采用积极的内存分配策略,这意味着即使返回了一个非空指针,并不一定能够保证内存中有足够的空间。。若不够,则OOM killer会杀掉若干个进程腾出空间。
在分配空间大小小于MMAP_THRESHOLD的时候,malloc使用brk()函数分配空间,若大于,则使用mmap函数作为真正的实现函数。MMAP_THRESHOLD默认大小是128kb,可以使用 mallopt函数修改。

mmap函数
       #include 
       void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
       int munmap(void *addr, size_t length);

mmap在调用他的程序的虚拟内存上创建一个新的映射,addr指向映射地址的起始地址,若为NULL,则内核自己选择。映射长度为length,proc参数决定这片地址的保护,如可读,可写,可执行,不可接触。 flag参数决定这片地址对其他进程是否可见。

brk函数
       #include 
       int brk(void *addr);
       void *sbrk(intptr_t increment);

brk()函数族改变调用程序的虚拟内存中数据段的结束位置(program break)增加这个位置来增加数据区大小以达到分配空间的目的。
glibc的brk是brk系统调用的一个包装,返回值略有不同,实作是一样的。

画图比较

在下图中,brk从已初始化数据区的最后面,向bss区开辟空间;mmap在对区域中分配空间

参考资料

linux中man手册

malloc
MALLOC(3)                  Linux Programmer's Manual                 MALLOC(3)

NAME
       malloc, free, calloc, realloc - allocate and free dynamic memory

SYNOPSIS
       #include 

       void *malloc(size_t size);
       void free(void *ptr);
       void *calloc(size_t nmemb, size_t size);
       void *realloc(void *ptr, size_t size);
       void *reallocarray(void *ptr, size_t nmemb, size_t size);

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       reallocarray():
           _GNU_SOURCE

DEscriptION
       The malloc() function allocates size bytes and returns a pointer to the
       allocated memory.  The memory is not initialized.  If size is  0,  then
       malloc()  returns either NULL, or a unique pointer value that can later
       be successfully passed to free().

       The free() function frees the memory space pointed  to  by  ptr,  which
       must  have  been  returned by a previous call to malloc(), calloc(), or
       realloc().  Otherwise, or if free(ptr) has already been called  before,
       undefined behavior occurs.  If ptr is NULL, no operation is performed.

       The  calloc()  function allocates memory for an array of nmemb elements
       of size bytes each and returns a pointer to the allocated memory.   The
       memory  is  set  to zero.  If nmemb or size is 0, then calloc() returns
       either NULL, or a unique pointer value that can later  be  successfully
       passed to free().

       The  realloc() function changes the size of the memory block pointed to
       by ptr to size bytes.  The contents will be unchanged in the range from
       the start of the region up to the minimum of the old and new sizes.  If
       the new size is larger than the old size, the added memory will not  be
       initialized.   If  ptr  is  NULL,  then  the call is equivalent to mal‐
       loc(size), for all values of size; if size is equal to zero, and ptr is
       not  NULL,  then  the  call  is equivalent to free(ptr).  Unless ptr is
       NULL, it must have been returned by an earlier call to  malloc(),  cal‐
       loc(),  or realloc().  If the area pointed to was moved, a free(ptr) is
       done.

       The reallocarray() function  changes  the  size  of  the  memory  block
       pointed  to  by  ptr to be large enough for an array of nmemb elements,
       each of which is size bytes.  It is equivalent to the call

               realloc(ptr, nmemb * size);

       However, unlike that realloc() call, reallocarray() fails safely in the
       case  where  the  multiplication  would  overflow.  If such an overflow
       occurs, reallocarray() returns NULL, sets errno to ENOMEM,  and  leaves
       the original block of memory unchanged.
RETURN VALUE
       The  malloc()  and calloc() functions return a pointer to the allocated
       memory, which is suitably aligned for any  built-in  type.   On  error,
       these functions return NULL.  NULL may also be returned by a successful
       call to malloc() with a size of zero, or by a successful call  to  cal‐
       loc() with nmemb or size equal to zero.

       The free() function returns no value.

       The realloc() function returns a pointer to the newly allocated memory,
       which is suitably aligned for any built-in type and  may  be  different
       from ptr, or NULL if the request fails.  If size was equal to 0, either
       NULL or a pointer suitable to be passed  to  free()  is  returned.   If
       realloc()  fails, the original block is left untouched; it is not freed
       or moved.

       On success, the reallocarray() function returns a pointer to the  newly
       allocated  memory.   On failure, it returns NULL and the original block
       of memory is left untouched.

ERRORS
       calloc(), malloc(), realloc(), and reallocarray()  can  fail  with  the
       following error:

       ENOMEM Out  of  memory.  Possibly, the application hit the RLIMIT_AS or
              RLIMIT_DATA limit described in getrlimit(2).

ATTRIBUTES
       For  an  explanation  of  the  terms  used   in   this   section,   see
       attributes(7).

       ┌─────────────────────┬───────────────┬─────────┐
       │Interface            │ Attribute     │ Value   │
       ├─────────────────────┼───────────────┼─────────┤
       │malloc(), free(),    │ Thread safety │ MT-Safe │
       │calloc(), realloc()  │               │         │
       └─────────────────────┴───────────────┴─────────┘
ConFORMING TO
       malloc(), free(), calloc(), realloc(): POSIX.1-2001, POSIX.1-2008, C89,
       C99.

       reallocarray() is a nonstandard extension that first appeared in  Open‐
       BSD 5.6 and FreeBSD 11.0.
NOTES
       By  default,  Linux  follows  an optimistic memory allocation strategy.
       This means that when malloc() returns non-NULL there  is  no  guarantee
       that  the  memory  really  is available.  In case it turns out that the
       system is out of memory, one or more processes will be  killed  by  the
       OOM   killer.    For   more   information,   see   the  description  of
       /proc/sys/vm/overcommit_memory and /proc/sys/vm/oom_adj in proc(5), and
       the Linux kernel source file documentation/vm/overcommit-accounting.

       Normally, malloc() allocates memory from the heap, and adjusts the size
       of the heap as required, using sbrk(2).  When allocating blocks of mem‐
       ory larger than MMAP_THRESHOLD bytes, the glibc malloc() implementation
       allocates the memory as a  private  anonymous  mapping  using  mmap(2).
       MMAP_THRESHOLD  is  128 kB  by  default,  but  is adjustable using mal‐
       lopt(3).  Prior to Linux 4.7 allocations performed using  mmap(2)  were
       unaffected  by  the  RLIMIT_DATA  resource limit; since Linux 4.7, this
       limit is also enforced for allocations performed using mmap(2).

       To avoid corruption in multithreaded  applications,  mutexes  are  used
       internally to protect the memory-management data structures employed by
       these functions.  In  a  multithreaded  application  in  which  threads
       simultaneously  allocate and free memory, there could be contention for
       these mutexes.  To scalably handle memory allocation  in  multithreaded
       applications,  glibc  creates  additional  memory  allocation arenas if
       mutex contention is detected.  Each arena is a large region  of  memory
       that  is  internally allocated by the system (using brk(2) or mmap(2)),
       and managed with its own mutexes.

       SUSv2 requires malloc(), calloc(), and realloc() to set errno to ENOMEM
       upon  failure.  Glibc assumes that this is done (and the glibc versions
       of these routines do this); if you use a private malloc  implementation
       that does not set errno, then certain library routines may fail without
       having a reason in errno.

       Crashes in malloc(), calloc(), realloc(), or free() are  almost  always
       related  to  heap corruption, such as overflowing an allocated chunk or
       freeing the same pointer twice.

       The malloc() implementation is tunable via environment  variables;  see
       mallopt(3) for details.

SEE ALSO
       valgrind(1), brk(2), mmap(2), alloca(3), malloc_get_state(3),
       malloc_info(3), malloc_trim(3), malloc_usable_size(3), mallopt(3),
       mcheck(3), mtrace(3), posix_memalign(3)

COLOPHON
       This page is part of release 4.15 of the Linux man-pages project.  A
       description of the project, information about reporting bugs, and the
       latest version of this page, can be found at
       https://www.kernel.org/doc/man-pages/.

GNU                               2017-09-15                         MALLOC(3)

mmap
MMAP(2)                    Linux Programmer's Manual                   MMAP(2)

NAME
       mmap, munmap - map or unmap files or devices into memory

SYNOPSIS
       #include 

       void *mmap(void *addr, size_t length, int prot, int flags,
                  int fd, off_t offset);
       int munmap(void *addr, size_t length);

       See NOTES for information on feature test macro requirements.

DEscriptION
       mmap()  creates a new mapping in the virtual address space of the call‐
       ing process.  The starting address for the new mapping is specified  in
       addr.   The  length argument specifies the length of the mapping (which
       must be greater than 0).

       If addr is NULL, then the kernel chooses the address at which to create
       the  mapping;  this  is the most portable method of creating a new map‐
       ping.  If addr is not NULL, then the kernel takes it as  a  hint  about
       where  to place the mapping; on Linux, the mapping will be created at a
       nearby page boundary.  The address of the new mapping  is  returned  as
       the result of the call.

       The contents of a file mapping (as opposed to an anonymous mapping; see
       MAP_ANonYMOUS below), are initialized using length  bytes  starting  at
       offset  offset  in  the  file (or other object) referred to by the file
       descriptor fd.  offset must be a multiple of the page size as  returned
       by sysconf(_SC_PAGE_SIZE).

       The  prot  argument describes the desired memory protection of the map‐
       ping (and must not conflict with the open mode of  the  file).   It  is
       either  PROT_NONE  or  the  bitwise  OR of one or more of the following
       flags:

       PROT_EXEC  Pages may be executed.

       PROT_READ  Pages may be read.

       PROT_WRITE Pages may be written.

       PROT_NONE  Pages may not be accessed.

       The flags argument determines whether updates to the mapping are  visi‐
       ble to other processes mapping the same region, and whether updates are
       carried through to the underlying file.  This behavior is determined by
       including exactly one of the following values in flags:

       MAP_SHARED
       MAP_PRIVATE
       MAP_ANON
       MAP_ANonYMOUS
       MAP_DENYWRITE
       MAP_EXECUTABLE
       MAP_FILE
       MAP_FIXED
    munmap()
       The munmap() system call deletes the mappings for the specified address
       range, and causes further references to addresses within the  range  to
       generate  invalid  memory references.  The region is also automatically
       unmapped when the process is terminated.  On the  other  hand,  closing
       the file descriptor does not unmap the region.

       The  address  addr must be a multiple of the page size (but length need
       not be).  All pages containing  a  part  of  the  indicated  range  are
       unmapped,  and  subsequent  references  to  these  pages  will generate
       SIGSEGV.  It is not an error if the indicated range  does  not  contain
       any mapped pages.

RETURN VALUE
       On success, mmap() returns a pointer to the mapped area.  On error, the
       value MAP_FAILED (that is, (void *) -1) is returned, and errno  is  set
       to indicate the cause of the error.

       On  success,  munmap() returns 0.  On failure, it returns -1, and errno
       is set to indicate the cause of the error (probably to EINVAL).
       

brk
BRK(2)                     Linux Programmer's Manual                    BRK(2)

NAME
       brk, sbrk - change data segment size

SYNOPSIS
       #include 

       int brk(void *addr);

       void *sbrk(intptr_t increment);

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       brk(), sbrk():
           Since glibc 2.19:
               _DEFAULT_SOURCE ||
                   (_XOPEN_SOURCE >= 500) &&
                   ! (_POSIX_C_SOURCE >= 200112L)
           From glibc 2.12 to 2.19:
               _BSD_SOURCE || _SVID_SOURCE ||
                   (_XOPEN_SOURCE >= 500) &&
                   ! (_POSIX_C_SOURCE >= 200112L)
           Before glibc 2.12:
               _BSD_SOURCE || _SVID_SOURCE || _XOPEN_SOURCE >= 500

DEscriptION
       brk()  and  sbrk()  change  the  location  of  the program break, which
       defines the end of the process's data segment (i.e., the program  break
       is the first location after the end of the uninitialized data segment).
       Increasing the program break has the effect of allocating memory to the
       process; decreasing the break deallocates memory.

       brk()  sets the end of the data segment to the value specified by addr,
       when that value is reasonable, the system has enough  memory,  and  the
       process does not exceed its maximum data size (see setrlimit(2)).

       sbrk() increments the program's data space by increment bytes.  Calling
       sbrk() with an increment of 0 can be used to find the current  location
       of the program break.

RETURN VALUE
       On success, brk() returns zero.  On error, -1 is returned, and errno is
       set to ENOMEM.

       On success, sbrk() returns the previous program break.  (If  the  break
       was  increased,  then this value is a pointer to the start of the newly
       allocated memory).  On error, (void *) -1 is returned, and errno is set
       to ENOMEM.

ConFORMING TO
       4.3BSD; SUSv1, marked LEGACY in SUSv2, removed in POSIX.1-2001.
NOTES
       Avoid  using  brk() and sbrk(): the malloc(3) memory allocation package
       is the portable and comfortable way of allocating memory.

       Various systems use various types for the argument of  sbrk().   Common
       are int, ssize_t, ptrdiff_t, intptr_t.

   C library/kernel differences
       The  return value described above for brk() is the behavior provided by
       the glibc wrapper function for the Linux brk() system call.   (On  most
       other  implementations,  the  return value from brk() is the same; this
       return value was also specified in SUSv2.)  However, the  actual  Linux
       system  call returns the new program break on success.  On failure, the
       system call returns the current break.  The glibc wrapper function does
       some  work  (i.e.,  checks  whether the new break is less than addr) to
       provide the 0 and -1 return values described above.

       On Linux, sbrk() is implemented as a library  function  that  uses  the
       brk()  system  call,  and does some internal bookkeeping so that it can
       return the old break value.

SEE ALSO
       execve(2), getrlimit(2), end(3), malloc(3)

COLOPHON
       This page is part of release 4.15 of the Linux  man-pages  project.   A
       description  of  the project, information about reporting bugs, and the
       latest    version    of    this    page,    can     be     found     at
       https://www.kernel.org/doc/man-pages/.

Linux                             2016-03-15                            BRK(2)

欢迎分享,转载请注明来源:内存溢出

原文地址:https://outofmemory.cn/zaji/5182584.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-11-18
下一篇2022-11-18

随机推荐

  • kk是什么意思

    “kk”在韩语中是笑的意思,“kk”可以理解为“哈哈”,同理kkkkk=哈哈哈哈哈,一种模拟笑声,表示开心或笑会经常被使用聊天短语。kk,聊天的时候k‌‌‌‌‌‌k表示一种催促让别人快点,快快的缩写。

    2022-12-06
    000
  • 洗衣服是什么内涵意思

    有对夫妻想爱爱的时候,都会以“洗衣服”做暗号,因此洗衣服是典型的夫妻之间的床笫暗语。某日,两人斗嘴吵架后,因为太太正在气头上,丈夫又有X爱上的需要,不方便开口向太太求爱,只好请儿子代为传话:“妈妈,爸

    2022-12-06
    000
  • 网络语渣男会呼吸渣女蹦野迪什么意思

    蹦野迪,意思是指啥都不懂,闷头乱蹦。既没有套路也跟不上节奏,满场地的乱甩。 如果非要找出一个和 " 蹦野迪 " 类似贴切的词儿,那大概只有 " 山驴逼 " 可以与之一较高下了。渣女蹦野迪,意思是调侃蹦

    2022-12-06
    000
  • 狗大户是什么意思

    狗大户,这个称呼最早说的是沙特阿拉伯,狗大户就是gold大户,是一种调侃的叫法,表示不差钱。因为沙特阿拉伯在中东地区,盛产石油黄金,如果把国家比喻成人的话,沙特阿拉伯就是典型土豪,啥也没有,就有钱和石

    2022-12-06
    000
  • 别野

    别野,是网络用语,对“别墅”的另一种称谓,对于大房子的讽刺性说法。如果你不会读墅【shu】这个字,那就读别野吧,或许是某些人第一次见到“别墅”这个词,因看错或者不理解而读错。更多是故意而为的调侃话语。

    2022-12-06
    000
  • 吕不韦是哪国人

    吕不韦先是卫国著名的商人,后又因为自己的雄心壮志成为秦国的政治家、思想家。其实嬴政在处理了嫪毐集团之后,并没有急于处罚吕不韦。等到第二年的时候,才撤去了吕不韦的职务,让他回到了自己的封地。可毕竟这样一

    2022-12-06
    100
  • 马王爷有几只眼

     在传说里马王爷长有三只眼,所以又称“三眼灵光”、“三眼灵曜”。马王爷就是马神,俗称马王爷,是道教的神明,也是中国民间信奉的神仙之一。马王爷的来历有好几种说法,有的说他是纣王的儿子殷郊,也有的说他是匈

    2022-12-06
    000
  • 荆轲为什么刺秦王

    荆轲刺秦王的原因为秦王兼灭各国兵锋直指燕国地界,为了维护自己国家的安危,太子丹决定派荆轲刺秦王。1、行刺背景公元前228年,秦国的将军王翦攻破赵国,俘虏赵王,占领了赵国大部分的国土,继而进军向北侵占土

  • 12星座赚钱最厉害的星座排名

    12星座赚钱头脑排名:1、天秤座:如果说经济头脑最强,那么排在首位的一定是天秤座。天秤座不仅善于理财,也很懂得如何去经营自己的财富。2、射手座:射手座在平时生活中不怕辛苦,乐于付出,即使面对再大的困难

    2022-12-06
    000

发表评论

登录后才能评论

评论列表(0条)

    保存