内存映射-

 

内存映射区不会堵塞

父子进程之间通信

/*
    #include <sys/mman.h>
    void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
    作用:将一个文件或者设备的数据映射到内存中
    参数:
        - addr:NULL
        - length:要映射的数据的长度,这个值不能为0,建议使用文件的长度
                    获取文件的长度:stat lseek
        - prot: 对申请的内存映射区的操作权限
            -PROT_EXEC:可执行的权限
            -PROT_READ:可读的权限
            -PROT_WRITE:可写的权限
            -PROT_NONE:没有权限
            要操作映射区,必须要有读的权限。PROT_READ或者PROT_READ | PROT_WRITE
        -flags:
            - MAP_SHARED:映射区的数据自动和磁盘文件进行同步,进程间通信,必须设置这个选项
            - MAP_PRIVATE:不同步,文件映射区的数据改变了,对原来的文件不会修改,会重新创造一个文件。
        -fd:需要映射的那个文件的文件描述符 (通过open得到,大小不能为0,open的权限不能和prot有冲突)
        -offset:偏移量,一般不用
    返回值:返回创建的内存的首地址,失败返回MAP_FAILED

    int munmap(void *addr, size_t length);
    功能:释放内存映射区
    参数:
        - addr:要释放的内存的首地址
        - length:要释放的内存的大小 与mmap的length一样大小

*/

/*
    使用内存映射实现进程间的通信:
    1.有关系的进程(父子进程)
        -还没有子进程的时候
            -通过唯一的父进程创建映射区
        -有了内存映射区之后,创建子进程
        -父子进程共享创建的内存映射区
    2.没有关系的进程之间的通信
        -准备一个大小不是0的磁盘文件
        -进程1:通过磁盘文件创建内存映射区
            - 得到一个操作这个内存的指针
        进程2:通过磁盘文件创建内存映射区
            - 得到一个操作这块内存的指针
        - 使用内存映射区通信
*/
#include<stdio.h>
#include<sys/mman.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.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 == NULL) {
        perror("mmap");
        exit(0);
    }
    pid_t pid = fork();
    if(pid > 0) {
        wait(NULL);
        char buf[128];
        strcpy(buf, (char*)ptr);
        printf("read : %s\n", buf);
        
    } else if(pid == 0) {
        strcpy((char*)ptr, "nihao, parent!");
    }

    munmap(ptr, size);

    return 0;
}

注意事项:

一:如果对mmap的返回值(ptr)做++操作(ptr++),munmap是否能成功?

void* ptr = mmap(.....);

ptr++;可以进行++操作

munmap(ptr,len) //错误,要保存地址

二:如果open时O_RDONLY,mmap时prot参数指定PROT_READ | PROT_WRITE会怎么样?

错误,返回MAP_FAILED

open()函数中的权限建议和prot参数的权限一样

三:如果文件的偏移量为1000?

偏移量必须为1024的整数倍

四:mmap什么情况下会调用失败?

        -第二个参数length = 0

        -第三个参数prot

                -只规定了写权限

                -open的权限小于prot的权限

        -第四个参数偏移量不是1024的整数倍

五:可以open的时候O_CREATE创建一个新文件来创建映射区吗?

可以,但是文件大小如果为0 肯定不行   可以对新的文件进行扩展(lseek   truncate)

六:mmap后关闭文件操作符,对mmap映射有没有影响?

不会有问题,此时的映射区还在

七:ptr越界操作怎么样?

越界操作的是非法内存,段错误

通过这个实现文件拷贝

#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<stdlib.h>
#include<sys/mman.h>
#include<string.h>
int main() {
    int fd = open("english.txt", O_RDWR);
    if(fd == -1) {
        perror("open");
        exit(0);
    }
    int length = lseek(fd, 0, SEEK_END);
    int fd1 = open("cpy.txt", O_RDWR | O_CREAT, 0664);
    if(fd1 == -1) {
        perror("open");
        exit(0);
    }
    truncate("cpy.txt", length);
    write(fd1, " ", 1);

    void* ptr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    void* ptr1 = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd1, 0);

    memcpy(ptr1, ptr, length);
    munmap(ptr1, length);
    munmap(ptr, length);
    close(fd1);
    close(fd);
    
}

通过mmap实现匿名映射

#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<stdlib.h>
#include<sys/mman.h>
#include<string.h>
#include<wait.h>

int main() {
    int len = 4096;
    void* ptr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);

    pid_t pid = fork();
    if(pid > 0) {
        strcpy((char*)ptr, "hello, world");
        wait(NULL);
    } else if(pid == 0) {
        sleep(1);
        printf("%s\n", (char*) ptr);
    }
    int ret = munmap(ptr, len);
    exit(0);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值