进程地址空间
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.