栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

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

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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)

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/450883.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号