Linux进程间通信之mmap(六)
1.mmap原理
存储映射I/O (Memory-mapped I/O) 使一个磁盘文件与存储空间中的一个缓冲区相映射。于是当从缓冲区中取数据,就相当于读文件中的相应字节。于此类似,将数据存入缓冲区,则相应的字节就自动写入文件。这样,就可在不适用read和write函数的情况下,使用地址(指针)完成I/O操作。 使用存储映射这种方法,首先应通知内核,将一个指定文件映射到存储区域中。这个映射工作可以通过mmap函数来实现。
2.Mmap映射
3.mmap使用
3.1.建立映射区
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
功能:
建立映射区。
参数:
addr:地址,填NULL。
length:长度,要申请的映射区的长度。
prot:权限。PROT_READ 可读 ; PROT_WRITE 可写。
flags: 标志位。MAP_SHARED 共享的 – 对映射区的修改会影响源文件; MAP_PRIVATE 私有的。
fd:文件描述符,需要打开一个文件。
offset:指定一个偏移位置 ,从该位置开始映射 。
返回值:
成功:返回映射区的首地址
失败:返回 MAP_FAILED ((void *) -1)
3.2.建立映射区
int munmap(void *addr, size_t length);
功能:
释放映射区。
参数:
addr:映射区的首地址。
length:映射区的长度。
返回值:
成功:返回0
失败:返回 -1
4.参考代码
4.1.使用共享内存映射实现两个进程之间的通信
(1)A进程
//=============================================================================
// File Name : process_mmap_communication_A.c
// Author : FengQQ
//
// Description : 使用共享内存映射实现两个进程之间的通信
// Annotation : 两个程序映射到同一个文件到自己的地址空间,进程A先运行,
// 每个两秒读取映射区域,看是否发生变化,进程B后运行,
// 它修改映射区域,然后退出,此时进程A能够观察到存储映射区的变化
//
// Created by FengQQ. 2020-10-02
//=============================================================================
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/msg.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <error.h>
int main(int argc,char *argv[])
{
int fd;
int ret;
struct stat sb;
char *mapped;
fd = open(argv[1],O_RDWR); //打开文件
if(fd < 0)
{
printf("open failed...\r\n");
}
ret = fstat(fd,&sb); //获取文件的属性
if(ret < 0)
{
printf("fstat failed...\r\n");
}
//将文件映射至进程的地址空间
mapped = (char *)mmap(NULL,sb.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
if(mapped < 0)
{
printf("mmap failed...\r\n");
}
close(fd); //文件已在内存, 关闭文件也可以操纵内存
while(1)
{
printf("%s\r\n",mapped); //每隔两秒查看存储映射区是否被修改
sleep(2);
}
return 0;
}
(2)B进程
//=============================================================================
// File Name : process_mmap_communication_B.c
// Author : FengQQ
//
// Description : 使用共享内存映射实现两个进程之间的通信
// Annotation : 两个程序映射到同一个文件到自己的地址空间,进程A先运行,
// 每个两秒读取映射区域,看是否发生变化,进程B后运行,
// 它修改映射区域,然后退出,此时进程A能够观察到存储映射区的变化
//
// Created by FengQQ. 2020-10-02
//=============================================================================
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/msg.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <error.h>
int main(int argc,char *argv[])
{
int fd;
int ret;
struct stat sb;
char *mapped;
fd = open(argv[1],O_RDWR); //打开文件
if(fd < 0)
{
printf("open failed...\r\n");
}
ret = fstat(fd,&sb); //获取文件的属性
if(ret < 0)
{
printf("fstat failed...\r\n");
}
//私有文件映射将无法修改文件
mapped = (char *)mmap(NULL,sb.st_size,PROT_READ|PROT_WRITE,MAP_PRIVATE,fd,0);
if(mapped < 0)
{
printf("mmap failed...\r\n");
}
close(fd); //映射完后, 关闭文件也可以操纵内存
mapped[20] = '9'; //修改一个字符
return 0;
}
4.2.通过匿名映射实现父子进程通信
//=============================================================================
// File Name : process_mmap_fork.c
// Author : FengQQ
//
// Description : 通过匿名映射实现父子进程通信
// Annotation :
//
// Created by FengQQ. 2020-10-02
//=============================================================================
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/msg.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <error.h>
#define BUF_SIZE 100
int main(int argc,char *argv[])
{
char *p_map;
//匿名映射,创建一块内存供父子进程通信
p_map = (char *)mmap(NULL,BUF_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);
if(fork() == 0)
{
sleep(1);
printf("chail got a message: %s\r\n",p_map);
sprintf(p_map,"%s","hi,dad,this is son.");
munmap(p_map,BUF_SIZE); //实际上,进程终止时,会自动解除映射
exit(0);
}
sprintf(p_map,"%s","hi, this is father");
sleep(2);
printf("parent got a message: %s\r\n",p_map);
return 0;
}
4.3.通过共享内存映射的方式修改文件
//=============================================================================
// File Name : process_mmap.c
// Author : FengQQ
//
// Description : 通过共享内存映射的方式修改文件
// Annotation : 运行: ./process_mmap data.txt
//
// Created by FengQQ. 2020-10-02
//=============================================================================
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/msg.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <error.h>
int main(int argc,char *argv[])
{
int fd;
int ret;
char *mapped;
struct stat sb;
fd = open(argv[1],O_RDWR); //打开文件
if(fd < 0)
{
printf("open failed...\r\n");
}
ret = fstat(fd,&sb); //获取文件的属性
if(ret < 0)
{
printf("fstat failed...\r\n");
}
//将文件映射至进程的地址空间
mapped = mmap(NULL,sb.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
if(mapped < 0)
{
printf("mmap failed...\r\n");
}
mapped[19] = 'a'; //修改一个字符,同步到磁盘文件
ret = msync((void *)mapped,sb.st_size,MS_SYNC); //同步用的存储器用映射的文件
if(ret < 0)
{
printf("msync failed...\r\n");
ret = munmap((void *)mapped,sb.st_size); //释放存储映射区
if(ret < 0)
{
printf("munmap failed...\r\n");
}
}
return 0;
}
Linux进程间通信之共享内存(七)
链接: link.(https://blog.csdn.net/qq_39721016/article/details/119618664)