C关于MMAP的思考

文章目录

mmap

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

/**
 * mmap
 * @return
 */
int main() {
    int fd = open("test.txt", O_RDWR | O_CREAT | O_TRUNC, 0664);
    if (fd == -1) {
        perror("error");
        exit(1);
    }
    //文件大小扩容10
    /*write(fd, '\0', 1);
    lseek(fd, 10, SEEK_SET);*/
    //同上2个函数
    ftruncate(fd, 20);
    int len = lseek(fd, 0, SEEK_END);
    /*
     * addr:指定缓冲区地址,这里null系统分配
     * len:指定缓冲区大小,不能为0,默认<=文件占用空间大小
     * prot:共享内存映射区读写属性
     * flags:共享属性,share则直接刷盘,private则独占,不会反映磁盘上.
     * offset:开始读取偏移位置,需要4k倍数
     *
     * 创建映射区,需要文件读权限.因为默认会执行一次读取操作,将文件内容映射缓冲区中.
     * 当操作缓冲区时,MAP_SHARED需要文件写权限,MAP_private因为只操作缓冲区,所以不要也可.
     */
    char *p = mmap(NULL, len, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
    if (MAP_FAILED == p) {
        perror("error");
        exit(1);
    }
    //缓冲区创建后,在操作缓冲区之前,文件描述符关闭,缓冲区也能有效操作.后续用地址读取文件
    close(fd);

//越界也能输入
//    strcpy(p + len -3, "hello2");


//当使用自增修改p值时,释放的时候失败.因为创建映射区的p和释放的p不一致.
//    strcpy(p++, "hello5");

strcpy(p, "hello5");
    int ret = munmap(p, len);
    if (ret == -1) {
        perror("error");
        exit(1);
    }
    return 0;
}

进程通信

file

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

/**
 * mmap父子进程和非血缘关系进程通信
 * MAP_SHARED:父子进程共享映射区
 * MAP_PRIVATE:父子进程各自独占映射区
 *
 *  通过mmap可重复读
 * @return
 */
void test() {
    //建立映射区
    int fd = open("test.txt", O_RDWR | O_CREAT | O_TRUNC, 0664);
    int var = 100;
    if (fd == -1) {
        perror("error");
        exit(1);
    }
    int size = 4;
    ftruncate(fd, size);
    int *p = (int *) mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
    if (MAP_FAILED == p) {
        perror("error");
        exit(1);
    }
    //关闭文件描述符,
    close(fd);

    //建立进程通信
    pid_t pid = fork();
    if (pid == 0) {
        *p = 2000;
        var = 1000;
        printf("%d %d \n", *p, var);

    } else {
        sleep(1);
        printf("%d %d \n", *p, var);
        wait(NULL);

        int ret = munmap(p, size);
        if (ret == 1) {
            perror("error");
            exit(1);
        }
    }

}

struct student {
    int age;
    char name[256];
    int count;
};

void test2() {
    struct student stu = {10, "hah", 0};
    //建立映射区
    int fd = open("test.txt", O_RDWR | O_CREAT | O_TRUNC, 0664);

    if (fd == -1) {
        perror("error");
        exit(1);
    }
    ftruncate(fd, sizeof(stu));
    struct student *p = (struct student *) mmap(NULL, sizeof(stu), PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
    if (MAP_FAILED == p) {
        perror("error");
        exit(1);
    }
    close(fd);

    while (1) {
        sleep(2);
//        strcpy(p->name, stu.name);
//同上
        char *dst = p->name;
        const char *src = stu.name;
        while ((*dst++ = *src++) != '\0');
        //同上
/*
        for (int i = 0; i < sizeof(stu.name); i++) {
            dst[i] = src[i];
        }
*/
        p->age = stu.age;
        p->count = stu.count++;
//同上2句
//memcpy(p, &stu, sizeof(stu));
        printf("%d %d  %s %p \n", p->age, p->count, p->name, p);
    }

    munmap(p, sizeof(stu));
}

int main() {
//    mmap父子进程通信
    test();

//非血缘关系
//缓冲区写入结构体
//可重复读
//    test2();

//匿名映射,只适合有血缘关系进程
    //1:可关闭文件描述符后,直接删除文件
        //    close(fd);
        //    unlink("test.txt");
    //2:直接设置MAP_ANONYMOUS即可,fd设置-1,大小可任意设置
        //   *p =  mmap(NULL,40, PROT_WRITE | PROT_READ, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
    //3:若没有MAP_ANONYMOUS,则通过空文件实现。
        //    int fd = open("/dev/zero", O_RDWR | O_CREAT | O_TRUNC, 0664);
    return 0;
}

file2

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

struct student {
    int age;
    char name[256];
    int count;
};

void test2() {
    struct student stu = {10, "hah"};
    //建立映射区
    int fd = open("test.txt", O_RDONLY, 0664);
    if (fd == -1) {
        perror("error");
        exit(1);
    }

    struct student *p = (struct student *) mmap(NULL, sizeof(stu), PROT_READ, MAP_SHARED, fd, 0);
    if (MAP_FAILED == p) {
        perror("error");
        exit(1);
    }
    close(fd);

    while (1) {
        sleep(1);
        printf("%d %d  %s %p \n", p->age, p->count, p->name,p);
    }
    munmap(p, sizeof(stu));
}

int main() {
    test2();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值