父子共享的信息:文件描述符,mmap建立的共享映射區(MAP_SHARED)
mmap父子間進程通信
var的時候 :讀時共享,寫時復制
父進程先創建映射區,指定共享MAP_SHARED權限 , fork創建子進程。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>
#include<sys/mman.h>
#include<fcntl.h>
#include<sys/wait.h>
int var = 100;
int main(int argc , char *argv[])
{int fd;pid_t pid;int *p;fd = open("text" , O_RDWR|O_CREAT|O_TRUNC , 0644);if(fd == -1){perror("open error");exit(1);}ftruncate(fd , 4);p = (int*)mmap(NULL, 4 , PROT_READ|PROT_WRITE , MAP_SHARED , fd , 0);if(p == MAP_FAILED){perror("mmap error");exit(1);}pid = fork();if(pid == 0){*p = 2000; //寫共享內存var = 1000; printf("I am child,mypid:%d , *p = %d , var = %d\n" , getpid() , *p ,var);}else{sleep(1);printf("I am parent , *p = %d , var = %d\n" , *p , var);wait(NULL);int ret = munmap(p , 4);if(ret == -1){perror("munmap error");exit(1);}}return 0 ;
}
mmap無血緣關系進程間通信(重點)
兩個進程打開同一個文件,創建映射區,指定flags為MAP_SHARED,一個進程寫入一個進程讀出。效率應該是最高的。?
為什么會映射到同一塊內存上,借用GPT:即使兩個沒有血緣關系(即非父子關系)的進程,分別 open()
同一個文件,然后使用 mmap()
映射這同一個文件,得到的指針 p
(虛擬地址)**可能不同,但它們最終指向的是同一塊 物理內存頁,因為 mmap
的核心是文件映射到物理頁幀,多個進程映射相同文件內容,就映射到了同一塊物理內存。
寫端:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>
#include<sys/mman.h>
#include<fcntl.h>
#include<sys/wait.h>struct student{int id ;char name[256];int age;
};int main(int argc , char *argv[])
{struct student stu = {1 , "xiaoming" , 19};int fd;int *p;fd = open("textw" , O_RDWR|O_CREAT|O_TRUNC , 0644);ftruncate(fd , sizeof(stu));printf("fdwrite:%d\n",fd);p = mmap(NULL, sizeof(stu) , PROT_READ|PROT_WRITE , MAP_SHARED , fd , 0);if(p == MAP_FAILED){perror("mmap error");exit(1);}close(fd);while(1){sleep(1);memcpy(p ,&stu ,sizeof(stu));stu.id++;}munmap(p , sizeof(stu));return 0;
}
讀端:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>
#include<sys/mman.h>
#include<fcntl.h>
#include<sys/wait.h>struct student{int id ;char name[256];int age;
};int main(int argc , char *argv[])
{struct student stu;int fd;struct student *p;fd = open("textw" , O_RDWR);printf("fd read: %d\n" , fd);p = mmap(NULL, sizeof(stu) , PROT_READ|PROT_WRITE , MAP_SHARED , fd , 0);if(p == MAP_FAILED){perror("mmap error");exit(1);}close(fd);while(1){printf("id:%d , name:%s , age:%d\n" , p->id , p->name , p->age);sleep(1);}munmap(p , sizeof(stu));return 0;
}
注意:無血緣關系進程間通信。FIFO:數據只能一次讀取
mmap:數據可以重復讀取。
匿名映射(了解)
void* mmap(NULL , size , PROT_READ|PROT_WRITE , MAP_SHARED|MAP_ANON , -1 ,0);size: 可以隨便寫
flags:需要寫MAP_ANON
fd : -1