私有内存与共享内存实验
本地内存
- 64位系统内核占据128T地址范围:0xFFFF FFFF FFFF FFFF – 0x0000 7FFF FFFF FFFF
- 64位系统进程占据128T地址范围:0x0000 7FFF FFFF FFFF – 0x0000 0000 0000 0000(从高到低:栈、映射、堆、BSS、数据、代码、保留)TOP的RES即实际用页表映射到物理内存的大小,使用多少映射多少,按需满足。从实验来看最小映射单位为4KB(用1个字节也映射4KB)。
共享内存
申请连续内存块
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
// gcc -g malloc.c -o malloc
void fun_sig(int sig) {
printf("recv sig %d, exit...\n",sig);
exit(0);
}
int main() {
int i;
size_t s;
char *ptr;
signal(SIGINT, fun_sig);
s = 100 * 1024 * 1024;
ptr = malloc(s);
for (i = 0; i < 100 * 1024 * 1024; i++) {
//if (i % (1024*1024) == 0)
*(ptr + i) = 0xFF;
}
printf("malloc done.\n");
while(1);
return 0;
}
下表为TOP与pmap的观测结果:
MALLOC SIZE | VIRT | RES | SHR | Address Kbytes RSS Dirty Mode Mapping (KB) |
---|---|---|---|---|
1MB|全用 | 10.2m | 1.5m | 0.4m | 00007fae3c165000 1028 1028 1028 rw— anon |
10MB|全用 | 19.2m | 10.5m | 0.4m | 00007faa7b378000 10244 10244 10244 rw— anon |
100MB|全用 | 109.2m | 100.5m | 0.4m | 00007f36eb3e4000 102404 102404 102404 rw— anon |
100MB|用1MB | 109.2m | 1.5m | 0.4m | 00007eff30578000 102404 1028 1028 rw— anon |
100MB|用50MB | 109.2m | 50.4m | 0.4m | 00007f996e3fb000 102404 51204 51204 rw— anon |
100MB|用100字节|每1M用1字节 | 109.2m | 0.9m | 0.4m | 00007f5473728000 102404 400 400 rw— anon |
100MB|用0字节 | 109.2m | 0.4m | 0.3m | 00007f1f7b2e7000 102404 4 4 rw— anon |
结论
这里针对线程无join、detach回收的场景做测试:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
// gcc -g -lpthread ph.c -o ph
void* worker(void* arg) {
// printf("c");
// char *xx = malloc(1000);
// *(xx) = 0x12;
// *(xx + 51) = 0x12;
// free(xx);
return NULL;
}
void fun_sig(int sig) {
printf("recv sig %d, exit...\n",sig);
exit(0);
}
int main() {
int i;
signal(SIGINT, fun_sig);
for (i = 0; i < 100000; i++) {
pthread_t t;
int ret;
ret = pthread_create(&t, NULL, worker, NULL);
if (ret != 0) {
printf("pthread_create error, ret=%d, i=%d.\n",ret, i);
while(i);
}
// pthread_join(t, NULL);
}
printf("all thread created.\n");
while(i);
return 0;
}
输出
pthread_create error, ret=11, i=32745.
在创建到32745个线程时,pthread框架报告没有资源创建新线程了,这个是框架自己对于内存使用的显示。
现在的TOP情况
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
26706 mingjie 20 0 256.0g 274.6m 0.6m R 100.0 0.9 0:16.87 ./ph
pmap情况
$ pmap -x 22359
00007f3cf591c000 8192 8 8 rw--- [ anon ]
00007f3cf611c000 4 0 0 ----- [ anon ]
00007f3cf611d000 8192 8 8 rw--- [ anon ]
00007f3cf691d000 4 0 0 ----- [ anon ]
00007f3cf691e000 8192 8 8 rw--- [ anon ]
00007f3cf711e000 4 0 0 ----- [ anon ]
...
...
$ pmap -x 22359 | grep 8192 | wc -l
32746
结论
32746 * 8MB = 255.8GB
,和VIRT基本持平。32745 * 8KB = 255MB
,和RES基本持平。线程泄露特征:大量8MB块无人回收、VIRT超级大。
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
char *addr;
size_t s = 100 * 1024 * 1024;
addr = mmap(NULL, s, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
// *addr = 1;
switch (fork())
{
case -1:
fprintf(stderr, "fork() failed\n");
exit(EXIT_FAILURE);
case 0:
printf("Child started, value = %d\n", *addr);
for (int i = 0; i < s; i++)
{
*(addr + i) = 0xFE;
}
printf("Child started, value = %d\n", *addr);
while(1);
exit(EXIT_SUCCESS);
default:
while(*(addr + s/2) != -2);
int kk;
for (int i = 0; i < s / 2; i++)
{
kk = *(addr + i);
}
while(kk);
if (wait(NULL) == -1)
{
fprintf(stderr, "wait() failed\n");
exit(EXIT_FAILURE);
}
printf("In parent, value = %d\n", *addr);
if (munmap(addr, sizeof(int)) == -1)
{
fprintf(stderr, "munmap()() failed\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
}
父VIRT | 父RES | 父SHR | 子VIRT | 子RES | 子SHR |
---|---|---|---|---|---|
111788 | 436 | 332 | 111792 | 108 | 0 |
父进程pmap
Address Kbytes RSS Dirty Mode Mapping
00007f9a61f8e000 102400 0 0 rw-s- zero (deleted)
子进程pmap
Address Kbytes RSS Dirty Mode Mapping
00007f9a61f8e000 102400 4 0 rw-s- zero (deleted)
父子进程的映射地址是相同的。
父VIRT | 父RES | 父SHR | 子VIRT | 子RES | 子SHR |
---|---|---|---|---|---|
111788 | 440 | 332 | 111792 | 102508 | 102392 |
父进程pmap
Address Kbytes RSS Dirty Mode Mapping
00007f12d530c000 102400 0 0 rw-s- zero (deleted)
子进程pmap
Address Kbytes RSS Dirty Mode Mapping
00007f12d530c000 102400 102400 102400 rw-s- zero (deleted)
子进程写入了100MB体现在在SHR中。
父VIRT | 父RES | 父SHR | 子VIRT | 子RES | 子SHR |
---|---|---|---|---|---|
111788 | 51636 | 51528 | 111792 | 102508 | 102396 |
父进程pmap
Address Kbytes RSS Dirty Mode Mapping
00007f236a1db000 102400 51204 51200 rw-s- zero (deleted)
子进程pmap
Address Kbytes RSS Dirty Mode Mapping
00007f236a1db000 102400 102400 102400 rw-s- zero (deleted)
父进程读取了50MB体现在SHR中。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有