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;
}