美文网首页
内存管理 #1

内存管理 #1

作者: 无无吴 | 来源:发表于2019-09-26 07:39 被阅读0次

    进程地址空间

    Pages and Paging

    bits => bytes => words => pages
    page是MMU(memory management unit)的最小地址单元
    虚拟地址空间被分割成pages。
    机器架构决定了page的size。一般来说32位的系统是4KB,64位的系统是8KB。

    Sharing and copy-on-write(COW)

    Memory Regions

    • text segment: code, string literals, constant variables, and other read-only data.
    • stack: process's execution stack.
    • data segment or heap:
    • bss segment: uninitialized global variables

    分配动态内存

    任何内存管理系统的foundation是分配,使用,和到最后的返还dynamic memory。

    // classic C interface for obtaining dynamic memory
    #include <stdlib.h>
    void *malloc(size_t size);
    
    char *p;
    /* give me 2 KB!*/
    p = malloc(2048);
    if(!p)
        perror("malloc");
    
    struct treasure_map *map;
    map = malloc(sizeof(struct treasure_map));
    if(!map)
        perror("malloc");
    
    //c++ need to typecast malloc()'s return
    char *name;
    /* allocate 512 bytes*/
    name = (char *)malloc(512);
    if(!name)
        perror("malloc");
    
    //wrapper of malloc
    // like malloc(), but terminates on failure
    void *xmalloc(size_t size)
    {
        void *p;
        p = malloc(size);
        if(!p){
              perror("xmalloc");
              exit(EXIT_FAILURE);  
        }
        return p;
    }
    

    Allocating Arrays

    #include <stdlib.h>
    void *calloc(size_t nr, size_t size);
    
    int *x, *y;
    x = malloc(50 * sizeof(int));
    if(!x){
          perror("malloc")l
          return -1;
    }
    y = calloc(50, sizeof(int));
    if(!y){
        perror("calloc");
        return -1;
    }
    

    虽然看上去是一样的,但上面两个的行为是不同的。malloc不保证分配内存的内容是什么,calloc会把分配到的内存走初始化位0。

    /* works identically to malloc(), but memory is zeroed*/
    void *malloc0(size_t size)
    {
        return calloc(1, size);
    }
    /* like malloc(), but zeros memory and terminated on failure*/
    void *xmalloc0(size_t size)
    {
        void *p;
        p = calloc(1, size);
        if(!p){
            perror("xmalloc0");
            exit(EXIT_FAILURE);
        }
        return p;
    }
    

    Resizing Allocations

    #include <stdlib.h>
    void *realloc(void *ptr, size_t size);
    

    If size is 0, 效果和free()是一样的。

    struct map *p;
    /* allocate memory for two map structures*/
    p = calloc(2, sizeof(struct map));
    if(!p){
        perror("calloc");
        return -1;
    }
    /* use p[0] and p[1]*/
    
    struct map *r;
    /* we now need memory for only one map*/
    r = realloc(p, sizeof(struct map));
    if(!r){
        /*note that 'p' is still valid!*/
        perror("realloc");
        return -1;
    }
    /*use 'r'*/
    free(r);
    

    如果调用返回失败,则p未被触及,因此仍然有效。我们可以继续使用它,并最终需要释放它。相反,如果调用成功,则忽略p,而使用r代替。

    Freeing Dynamic Memory

    #include <stdlib.h>
    void free(void *prt);
    

    Alignment

    在编写可移植代码时,程序员必须小心避免违反对齐要求。

    Allocating alignment memory

    在大多数情况下,编译器和C库透明地处理对齐参数.POSIX命令通过malloc()、calloc()和realloc()返回的内存对齐以供任何一种标准的C类型使用。在linux上,这些函数总是返回在32位系统上沿着8字节边界对齐的内存,在64位系统上返回沿16字节边界对齐的内存。

    /* one or the other -- either suffices */
    #define _XOPEN_SOURCE 600
    #define _GNU_SOURCE
    #include <stdlib.h>
    int posix_memalign (void **memptr, size_t alignment, size_t size);
    

    成功的调用将返回0,并且分配size大小并且按照alignment大小对齐的动态内存。
    失败的话,会设置errno。

    char *buf;
    int ret;
    /* allocate 1 KB along a 256-byte boundary */
    ret = posix_memalign (&buf, 256, 1024);
    if (ret) {
        fprintf (stderr, "posix_memalign: %s\n",
        strerror (ret));
        return −1;
     }
    /* use 'buf'... */
    free (buf);
    

    Other alignment concerns

    Managing the Data Segment

    堆中的动态内存分配从段的底部向上增长;栈从段的顶部向下扩展到堆。
    将两者分开的分界线称为断点或断点。

    #include <unistd.h>
    int brk (void *end);
    void * sbrk (intptr_t increment);
    

    A call to brk() sets the break point (the end of the data segment) to the address specified by end. On success, it returns 0. On failure, it returns −1 and sets errno to ENOMEM.
    A call to sbrk() increments the end of the data segment by increment bytes, which may be a positive or negative delta. sbrk() returns the revised break point. Thus, an increment of 0 provides the current break point:

        printf ("The current break point is %p\n", sbrk (0));
    

    Deliberately, both POSIX and the C standard define neither of these functions. Nearly all Unix systems, however, support one or both. Portable programs should stick to the standards-based interfaces.

    相关文章

      网友评论

          本文标题:内存管理 #1

          本文链接:https://www.haomeiwen.com/subject/uxvluctx.html