进程间通信:mmap内存映射区


void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
功能:申请一块内存空间,可以将它作为进程通讯的共享内存,也可以将文件直接映射到其中。
返回值:成功返回指向内存的首地址,失败返回MAP_FAILED并设置errno
参数

  • addr:允许用户将某个特定的地址设为这段内存的起始地址,设为NULL表示系统自动分配一个地址
  • prot:访问权限PROT_READ、PROT_WRITE、PROT_EXEC、PROT_NONE
  • fd:被映射的文件对应的文件描述符
  • offset:设置从文件的何时开始映射
  • flags:控制内存段内容被修改后程序的行为
flags
MAP_SHARED在进程间共享这段内存。对内存的修改将反映到被映射的文件中
MAP_PRIVATE内存段为调用进程私有。对内存的修改不会反映到被映射的文件中
MAP_ANONYMOUS这段内存不是从文件映射而来的。其内容被初始化为全0。这种情况下,mmap函数的最后两个参数将被忽略
MAP_FIXED内存段必须位于addr参数指定的地址处。addr必须是内存页面大小(4096字节)的整数倍
MAP_HUGETLB按照"大内存页面"来分配内存空间,大内存页面的大小可以通过/proc/meminfo文件查看

int munmap(void *addr, size_t length);
返回值:成功返回0,失败返回-1并设置errno


1. 父子进程是否会共享mmap创建的内存映射区?

答:父子进程会共享mmap创建的内存映射区

2.1 使用mmap在[父子]进程间通信

  1. 父子进程如何使用mmap进行通信?
    父子进程都使用父进程调用mmap返回的指向内存映射区的ptr指针
  2. mmap创建的内存映射区,是非阻塞的。
    与pipe不同的是,内存映射区是非阻塞的—>因此应该控制父子进程的read和write顺序。(必须保证内存映射区中被写入数据时,才去读数据)
int main(){                                                                                                                      
  int len=4096;      
  //创建匿名的内存映射区                              
    //第四个参数,加上MAP_ANION:MAP_SHARED|MAP_ANON
    //fd指定为-1                                                                                      
  void* ptr=mmap(NULL,len,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANON,-1,0);                                                       
  
  if(ptr==MAP_FAILED){                                                                                                           
    perror("mmap");                                                                                                              
    exit(1);                                                                                                                     
  }                                                                                                                              
                                                                                                                                 
  pid_t pid=fork();                                                                                                              
  if(pid==-1){                                                                                                                   
    perror("fork");                                                                                                              
    exit(1);                                                                                                                     
  }                                                                                                                              
  if(pid>0){ //parent                                                                                                            
    strcpy((char*)ptr,"I am a student");  //向mmap中写入数据                                                                                       
    wait(NULL);                                                                                                                  
  }                                                                                                                              
  if(pid==0){//chile                                                                                                            
    printf("%s\n",(char*)ptr);  //从mmap中读取数据                                               
  }                                                                                                                              
  munmap(ptr,len);                                                                                                                                                                                                                                             
  return 0;                                                                                                                      
}  

2.2 使用mmap在[无血缘关系]进程间通信**

Question:父子进程如何使用mmap进行通信?(即:父子进程通信,怎么找到同一个mmap内存映射区?)
答:本地磁盘上的(绑定相同的文件)

  1. 如何通信? 答:不能使用匿名映射的方式(只能借助磁盘文件创建映射区)
  2. 进程A(a.c) 进程B(b.c)通信案例
- a.c
  int fd=open("hello");
  void* ptr=mmap(.....fd.....);
  对映射区ptr进行读写操作
- b.c
  int fd=open("hello");
  void* ptr=mmap(.....fd.....);
  对映射区ptr进行读写操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值