内存管理 #1

进程地址空间

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 
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 
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 
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 
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 
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 
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)