内存映射(1)

内存映射允许程序通过修改内存来直接修改磁盘文件,通过mmap系统调用实现。MAP_SHARED标志确保数据同步,而MAP_PRIVATE则不更新原文件。munmap用于释放内存。在父子进程间,通过共享内存映射区实现非阻塞通信,而在无关联进程间,通过同一磁盘文件创建映射区达到相同效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

内存映射

磁盘文件中的数据映射到内存,用户通过修改内存就能修改磁盘文件

相关的系统调用:

 void *mmap()

功能:将一个文件或设备的数据映射到内存中

参数:

  1.         void *addr : NULL 由内核指定
  2. length : 要映射的数据长度,这个值不能为0,建议使用文件的长度。获取文件的长度,stat,lseek
  3. port : 对申请映射区的操作权限
    1. PORT_EXEC : 可执行的权限
    2. PORT_READ : 读权限
    3. PORT_NONE :没有权限
    4. 要操作映射区必须要有读权限
  4. flags : 
    1. MAP_SHARED : 映射区的数据会自动和磁盘文件进行同步,进程间通信必须要设置这个选项
    2. MAP_PRIVATE : 不同步,内存映射区的数据改变了对原来的文件不会进行修改,会重新创建一个新的文件
  5. fd :需要映射的文件的文件描述符
    1. 通过open得到,open的是一个磁盘文件
    2. 注意:文件的大小不能为0,open指定的权限不能和port参数有冲突
      1. open:只读/读写   port:PORT_READ
      2. open:读写           port : PORT_READ | PORT_WRITE
  6. offset : 偏移量,一般不用
  7. 返回值:返回创建的内存的首地址,失败返回MAP_FAILED,

int munmap()

  1. 功能:释放内存
  2. 参数:
    1. addr :要释放的内存首地址
    2. length :释放的内存大小

 使用内存映射实现进程间通信:

  1. 有关系的·进程(父子进程)
    1. 通过唯一父进程,创建内存映射区
    2. 然后创建子进程
    3. 父子进程共享创建的内存映射区
  2. 没有关系的进程间通信:
    1. 准备一个大小不是0的磁盘文件
    2. 进程1:通过磁盘文件创建内存映射区,得到一个操作这块内存的指针
    3. 进程2:通过磁盘文件创建内存映射区,得到一个操作这块内存的指针
    4. 使用内存映射区进行通信

注意:内存映射区通信,是非阻塞的。

实现

父进程读取到子进程输入的数据

/*
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);

int munmap(void *addr, size_t length);
*/
#include<stdio.h>
#include<sys/mman.h>
#include<fcntl.h>
#include<sys/types.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<wait.h>
int main(){
    //打开一个文件
    int fd = open("test.txt",O_RDWR);
    //获取文件的大小
    int size = lseek(fd,0,SEEK_END);
    //创建内容映射区
    void *ptr = mmap(NULL,size,PROT_READ | PROT_WRITE, MAP_SHARED, fd , 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);
        printf("read data : %s\n",buf);
    }
    else if(pid == 0)
    {
        //子进程
        strcpy((char *)ptr,"nihao!!!!");

    }
    //关闭内存映射区
    munmap(ptr,size);
    return 0;
}

 

 文件也发生了改变

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值