版权声明: https://blog.csdn.net/dashoumeixi/article/details/83866049
mmap 参数 :
addr : 依据边界颗粒度 (提升到某个页面的整数倍)
length , offset : 总是某个页面的整数倍
页面大小 : sysconf(_SC_PAGE_SIZE); 一般 4096 或 8192
基础:
如果映射大小超过了文件大小 , 则在映射区写入的字节将被丢弃
以下例子 可使用 od -b -A d 1.dat 来查看写入情况
int fd = open("1.dat",O_RDWR|O_CREAT|O_TRUNC,0777);
ftruncate(fd,5000);
//这里是 4096 字节
int pagesize = sysconf(_SC_PAGE_SIZE);
printf("pagesize : %d\n", pagesize);
//1024 被提升到 4096 字节.
char *p = (char*)mmap(NULL,1024,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
p[pagesize - 1] = 1;
printf("p[%d] = %d\n" , pagesize,p[pagesize - 1]);
//p[pagesize] = 1; //出错 . 超出了映射范围
int fd = open("1.dat",O_RDWR|O_CREAT|O_TRUNC,0777);
ftruncate(fd,5000);
//这里是 4096 字节
int pagesize = sysconf(_SC_PAGE_SIZE);
printf("pagesize : %d\n", pagesize);
//5000 被提升 8192 字节
char *p = (char*)mmap(NULL,5000,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
p[pagesize - 1] = 1;
printf("p[%d] = %d\n" , pagesize,p[pagesize - 1]);
//文件大小 5000 , 而映射区有8192,超出文件大小的映射区可读写,但不会写入文件
p[8191] = 1;
printf("p[%d] = %d\n" , 8191,p[8191]);
int fd = open("1.dat",O_RDWR|O_CREAT|O_TRUNC,0777);
ftruncate(fd,5000);
//这里是 4096 字节
int pagesize = sysconf(_SC_PAGE_SIZE);
printf("pagesize : %d\n", pagesize);
//映射 20000 个字节 , 但实际映射成8192字节
char *p = (char*)mmap(NULL,20000,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
//出错了 。 一旦映射大小 超过了文件本身,将以文件大小提升成页面整数
p[8192] = 1;
printf("p[%d] = %d\n" , 8192,p[8192]);
1. 基于有名信号量
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <stdio.h>
#include <sys/mman.h>
int main(int argc , char ** argv , char ** env)
{
int zero = 0 , times = 10;
int fd = open("1.dat",O_RDWR|O_CREAT,0777);
write(fd,&zero,sizeof(int));
//addr : 边界颗粒度 . length , offet : 页面的倍数
//MAP_SHARED : 所做的操作都直接写入硬盘
int *ptr = mmap(NULL,sizeof(int),PROT_WRITE|PROT_READ,
MAP_SHARED,fd,0);
sem_t * sem = sem_open("/testsem",O_CREAT|O_EXCL,0777,1);
sem_unlink("testsem");
close(fd);
setbuf(stdout,NULL);
if(0 == fork()){
for(int i = 0 ; i < times; ++i){
sem_wait(sem);
printf("child count:%d\n" , (*ptr)++);
sem_post(sem);
}
return 0;
}
for(int i = 0 ; i< times;++i){
sem_wait(sem);
printf("parent count:%d\n" , (*ptr)++);
sem_post(sem);
}
return 0;
}
2.基于内存信号量:
struct shareobject{
sem_t sem;
int count;
} shared;
int main()
{
int times = 10;
int fd = open("1.dat",O_RDWR|O_CREAT,0777);
write(fd,&shared,sizeof(shared));
/*
把内存信号量写入文件,通过mmap 映射后,
相当于一个共享内存.
在共享内存里读写
*/
struct shareobject * p = (struct shareobject *)mmap(NULL,sizeof(shared),PROT_WRITE|PROT_READ,MAP_SHARED,
fd,0);
sem_init(&p->sem,1,1);
if(0 == fork()){
for(int i = 0 ; i < times ; ++i){
sem_wait(&p->sem);
printf("child count : %d\n" , p->count++);
sem_post(&p->sem);
}
return 0;
}
for(int i =0 ; i< times; ++i){
sem_wait(&p->sem);
printf("parent count : %d\n" , p->count++);
sem_post(&p->sem);
}
close(fd);
return 0;
}