我是靠谱客的博主 自由蛋挞,最近开发中收集的这篇文章主要介绍进程间通信:内存映射基本概念相关系统调用使用内存映射进程通信:(是非阻塞通信。)父子进程通过内存映射通信;内存映射注意事项匿名映射,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

基本概念

相关系统调用

使用内存映射进程通信:(是非阻塞通信。)

父子进程通过内存映射通信;

内存映射注意事项

匿名映射


基本概念

将磁盘文件映射到内存,用户修改内存就可以直接修改磁盘文件。(修改内存快很多,改磁盘很慢)。


相关系统调用

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

            映射长length(非0)的磁盘文件到addr(nullptr则自动选择一个)。
            stat lseek可以获取文件长度(当小于分页大小,会至少指定一个分页大小)
            prot:对申请的内存映射区的操作权限。 PROT_EXEC  PROT_WRITE PROT_READ  PROT_NONE       要操作,必须有读的权限
            flags:MAP_SHARED 映射区数据会自动和磁盘文件同步,进程通信必须设置
                     MAP_PRIVATE 不同步,映射区修改后,创建一个新文件
            fd:open()得到的映射文件的fd,大小不能为0. open指定权限与prot不能冲突

            offset:偏移量,必须是4k的整数倍,一般不偏移,置0.、

            成功返回创建的内存的首地址 失败返回MAP_FAILED   (void*) -1;

  int munmap(void *addr, size_t length); 释放内存映射 数值同上。


使用内存映射进程通信:(是非阻塞通信。)

        1 有关系的进程: 先映射,再fork()  父子进程共享创建的内存映射区

        2 没有关系:准备一个大小非0的磁盘文件,

                              进程1以此创建内存映射区,得到操作该内存的指针,

                              进程2也以此创建内存映射区,得到操作该内存的指针,  两个以此通信。

父子进程通过内存映射通信;

#include <sys/mman.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <cstring>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main()
{ 
   
    int ret=open("test.txt",O_RDWR);
    int size=lseek(ret,0,SEEK_END);
 //内存映射
    void* ptr=mmap(nullptr,size,PROT_READ|PROT_WRITE,MAP_SHARED,ret,0);
    if(ptr==MAP_FAILED)
    {
        perror("mmap:");
        exit(0);
    }
    pid_t pid=fork();

    if(pid>0)
    {//父进程
        wait(NULL);
        char buf[64];
        strcpy(buf,(char*)ptr);
        std::cout<<"parent read: "<<buf<<" "<<getpid()<<std::endl;
    }
    else if(pid==0)
    {
        //子进程
        strcpy((char*)ptr,"today is a good day");
    }
    std::cout<<"i am here "<<getpid()<<"n";
    munmap(ptr,size);
}

内存映射注意事项

1 mmap返回的ptr,可以++,但是++后munmap(ptr,len)会发生错误。 所以++前要先保存一份。

open指定权限与prot不能冲突,MAP_FAILED

3 文件偏移量必须是4k整数倍,否则返回MAP_FAILED

磁盘文件大小非0

5 open时可以O_CREAT创建新文件,但为了文件大小非0,需要对其扩展,lseek/ftruncate。

  int ret=open("lseek.txt",O_CREAT|O_RDWR,0664);

  lseek(ret,20,SEEK_END);

  char *wrbuf= "hjhk";

  write(ret,wrbuf,strlen(wrbuf));    扩展并写入文件大小才能生效
或者//
   ftruncate(ret,20);
   //truncate("lseek.txt",20)

6 mmap后关闭fd,对mmap无影响。 

7 void*ptr=mmap()   ptr越界操作的时非法内存,会产生段错误(当程序试图访问不允许访问内存位置,或试图以不允许的方式访问内存位置(例如尝试写入只读位置,或覆盖部分操作系统)时会发生段错误)。

8 可以用来实现文件复制。旧文件和要复制的文件分别映射后, memcpy(ptr1,ptr,len)进行内存复制。

匿名映射

不需要文件实体进行内存映射。可用于父子进程通信。 flag设置MAP_ANONYMOUS   fd=-1;

 void* ptr=mmap(nullptr,4096,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);
   

最后

以上就是自由蛋挞为你收集整理的进程间通信:内存映射基本概念相关系统调用使用内存映射进程通信:(是非阻塞通信。)父子进程通过内存映射通信;内存映射注意事项匿名映射的全部内容,希望文章能够帮你解决进程间通信:内存映射基本概念相关系统调用使用内存映射进程通信:(是非阻塞通信。)父子进程通过内存映射通信;内存映射注意事项匿名映射所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部