linux 内存管理、进程的映射、mmap()函数 、mallco()函数的缓冲机制

    今天总结 linux的内存管理、进程的映射以及介绍两个函数  mmap();和malloc()函数

    首先linux系统中,有物理地址、虚拟地址、虚拟内存这样的说法。

    物理地址:物理内存上的地址。 

    虚拟地址:物理地址的映射。

    虚拟内存:每个程序运行时都有自己的虚拟内存,32位机器一共4G的虚拟内存,其中0~(3G-1)叫做用户态,(3G-1)~4G叫做内核态。

    在用户态中又分为: 代码段、数据段、栈段、堆(栈和堆中间为动态库,下面又有证明)。

    下面我们来看当程序运行时,我们平时写的代码、声明的变量等都在那些段里。

     补充两点:一、什么叫进程?  答:程序运行起来就是进程。

                       二、操作系统会管理每一个进程,通过一个id来管理,这个id叫做pid,通过函数getpid()来获得。然后通过查看/grop/id号码/maps  可以查看进程中用户态的分配的状态。

    下面写一个简单的函数如下:

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include <sys/types.h>
  4 #include <unistd.h>
  5 int main(){
  6     int id=getpid();
  7     int a=10;
  8     int *p1=(int *)malloc(1024);
  9     int *p2=(int *)malloc(1024);
 10     int *p3=(int *)malloc(1024*4*35);
 11     printf("pid=%d\n",id);
 12     printf("a的地址=%p\n",&a);
 13     printf("p1里的地址=%p\n",p1);
 14     printf("p2里的地址=%p\n",p2);
 15     printf("p3里的地址=%p\n",p3);
 16     getchar();
 17     return 0;
 18 }
运行结果如下:

tarena@ubuntu:~/LIANXI/10.12$ ./a.out
pid=19468
a的地址=0x7fff794913c8
p1里的地址=0xa14010
p2里的地址=0xa14420
p3里的地址=0x7f5d46ba5010
采用 cat /proc/19468/maps得到如下结果:

tarena@ubuntu:~/LIANXI/10.12$ cat /proc/19468/maps
00400000-00401000 r-xp 00000000 08:01 1982110                            /home/tarena/LIANXI/10.12/a.out
00600000-00601000 r--p 00000000 08:01 1982110                            /home/tarena/LIANXI/10.12/a.out
00601000-00602000 rw-p 00001000 08:01 1982110                            /home/tarena/LIANXI/10.12/a.out
00a14000-00a35000 rw-p 00000000 00:00 0                                  [heap]
7f5d465fe000-7f5d467b3000 r-xp 00000000 08:01 397377                     /lib/x86_64-linux-gnu/libc-2.15.so
7f5d467b3000-7f5d469b3000 ---p 001b5000 08:01 397377                     /lib/x86_64-linux-gnu/libc-2.15.so
7f5d469b3000-7f5d469b7000 r--p 001b5000 08:01 397377                     /lib/x86_64-linux-gnu/libc-2.15.so
7f5d469b7000-7f5d469b9000 rw-p 001b9000 08:01 397377                     /lib/x86_64-linux-gnu/libc-2.15.so
7f5d469b9000-7f5d469be000 rw-p 00000000 00:00 0 
7f5d469be000-7f5d469e0000 r-xp 00000000 08:01 397357                     /lib/x86_64-linux-gnu/ld-2.15.so
7f5d46ba5000-7f5d46bcc000 rw-p 00000000 00:00 0 
7f5d46bdc000-7f5d46be0000 rw-p 00000000 00:00 0 
7f5d46be0000-7f5d46be1000 r--p 00022000 08:01 397357                     /lib/x86_64-linux-gnu/ld-2.15.so
7f5d46be1000-7f5d46be3000 rw-p 00023000 08:01 397357                     /lib/x86_64-linux-gnu/ld-2.15.so
7fff79473000-7fff79494000 rw-p 00000000 00:00 0                          [stack]
7fff795fe000-7fff79600000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
 运行结果中a的地址在 stack中,红色的部分。                  

p1,p2的地址在 heap 中,蓝色的部分。

p3的地址在黄色的部分中。

以上这些地址都是虚拟地址。

我们把a的地址相减等于十进制的33;

           p1和p2的地址相减等于十进制的33;

           p3的地址相减等于十进制的39;

注:实际物理地址中以页为单位来映射,一页等于4K。

所以:

当使用malloc向系统发出请求,需要一块1024字节(1k)的空间的时候,系统会直接分配33页的空间。

当第二次向系统发出请求,又需要一块1024字节的空间的时候,系统会在第一次分配的33页中来分配。

当第三次想系统发出请求,又需要35页的时候,系统分配了39页,多出来的根据ubuntu的系统位数不同,用途不同。我的是64位的,暂时想不出他们的用途分别是 什么。。。有知道的欢迎指导!  32位的机器是多出两页,分别是与动态库的隔膜和存放一些信息的。

前面第一次想系统发出请求,系统直接给了33页(你只需要一页的1/4),这个就叫做malloc的缓冲机制。

下面介绍mmap()函数

它的形式参数有:

  void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);

功能:在当前进程的虚拟地址里创建一个映射(与物理地址的映射)

参数:

         addr:一般直接NULL

         lehgth:指定映射区域的长度

         prot: 对这块地址的操作选择  选择多个时用按位或  |

                  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.//不能被访问的

         flags:

                  MAP_SHARED   对映射区域的更新可以被其他映射同一块区域的进程看到,对内存的更新同步到文件
                  MAP_PRIVATE   对映射区域的更新不能被其他映射到同一区域的进程看到,不会同步 到文件    
                  MAP_ANONYMOUS   不支持对任何文件的映射 fd 和 offset 被忽略

         fd:-1

         offset:0

返回值:指向所映射的地址的指针void 型。

函数如下:

  1 #include<stdio.h> 
  5 #include<string.h>
  6 #include <sys/mman.h>
  7 int main(){
  8     int prot=PROT_READ | PROT_WRITE;
  9     int flags=MAP_PRIVATE | MAP_ANONYMOUS;
 10     int fd=-1;
 11     void *p=mmap(NULL,1024,prot,flags,fd,0);
 12     strcpy(p,"hello world!");
 13     printf("%s\n",(char *)p);
 14     munmap(p,1024);
 15     p=NULL;    
 17     return 0;
 18 }
运行结果如下:

tarena@ubuntu:~/LIANXI/10.12$ gcc main.c
tarena@ubuntu:~/LIANXI/10.12$ ./a.out
hello world!

可以看出我们直接对p所指向的空间进行了操作。

前面介绍的malloc函数时向系统请求一块存储区,他的实质就是mmap()函数,系统在malloc()函数中调用了mmap()函数。








  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值