共享内存用于进程间通信
共享内存在父子进程间通信
示例
/*
* function: 演示使用mmap()函数实现使用共享映射区完成父子进程间通信
*
* 2020-12-07
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
int main(int argc, char *argv[])
{
// 打开一个文件
int fd = open("tmp", O_RDWR | O_CREAT | O_TRUNC, 0644);
if (fd == -1)
{
perror("open faild");
exit(1);
}
// 扩展文件大小, 需要打开的文件具有可写属性
if (ftruncate(fd, 20) == -1)
{
perror("ftruncate faild");
exit(1);
}
// 获取文件大小
off_t n = lseek(fd, 0, SEEK_END);
if (n == -1)
{
perror("lseek faild");
exit(1);
}
// 将文件映射到共享内存中
char *p = NULL;
p = (char *)mmap(NULL, n, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (p == MAP_FAILED)
{
perror("mmap failed");
exit(1);
}
pid_t pid = 0;
pid = fork();
if (pid == -1)
{
perror("fork faild");
exit(1);
}
else if (pid == 0) // 子进程
{
strcpy(p, "hello mmap");
printf("子进程完成写共享内存操作\n");
}
else // 父进程
{
sleep(1); // 睡眠一秒,让子进程完成写共享内存操作
printf("%s\n", p);
printf("父进程完成读共享内存操作\n");
}
// 系统调用删除指定地址范围的映射
if(munmap(p, n) == -1)
{
perror("mumap faild");
exit(1);
}
close(fd);
return 0;
}
共享内存在无血缘关系进程间通信
写端示例
/*
* function: 演示使用mmap()函数实现使用共享映射区完成无血缘关系进程间通信
* 此进程为写端
*
* 2020-12-07
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
int main(int argc, char *argv[])
{
// 打开一个文件
int fd = open("tmp", O_RDWR | O_CREAT | O_TRUNC, 0644);
if (fd == -1)
{
perror("open faild");
exit(1);
}
// 扩展文件大小, 需要打开的文件具有可写属性
if (ftruncate(fd, 20) == -1)
{
perror("ftruncate faild");
exit(1);
}
// 获取文件大小
off_t n = lseek(fd, 0, SEEK_END);
if (n == -1)
{
perror("lseek faild");
exit(1);
}
// 将文件映射到共享内存中
char *p = NULL;
p = (char *)mmap(NULL, n, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (p == MAP_FAILED)
{
perror("mmap failed");
exit(1);
}
// 写共享内存
strcpy(p, "hello world");
printf("写共享内存完成\n");
// 系统调用删除指定地址范围的映射
if(munmap(p, n) == -1)
{
perror("mumap faild");
exit(1);
}
close(fd);
return 0;
}
读端示例
/*
* function: 演示使用mmap()函数实现使用共享映射区完成无血缘关系进程间通信
* 此进程为读端
* 2020-12-07
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
int main(int argc, char *argv[])
{
// 打开一个文件
int fd = open("tmp", O_RDWR);
if (fd == -1)
{
perror("open faild");
exit(1);
}
// 获取文件大小
off_t n = lseek(fd, 0, SEEK_END);
if (n == -1)
{
perror("lseek faild");
exit(1);
}
// 将文件映射到共享内存中
char *p = NULL;
p = (char *)mmap(NULL, n, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (p == MAP_FAILED)
{
perror("mmap failed");
exit(1);
}
// 读共享内存
printf("%s\n", p);
printf("读共享内存完成\n");
// 系统调用删除指定地址范围的映射
if(munmap(p, n) == -1)
{
perror("mumap faild");
exit(1);
}
close(fd);
return 0;
}
匿名映射
只能用于有血缘关系进程间通信
Linux
通过mmap函数第4个参数,使用MAP_ANONYMOUS (或 MAP_ANON)完成匿名映射。
示例
/*
* function: 演示使用mmap()函数实现匿名映射完成父子进程间通信
*
* 2020-12-08
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
int main(int argc, char *argv[])
{
// 将文件映射到共享内存中
char *p = NULL;
size_t n = 20;
p = (char *)mmap(NULL, n, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (p == MAP_FAILED)
{
perror("mmap failed");
exit(1);
}
pid_t pid = 0;
pid = fork();
if (pid == -1)
{
perror("fork faild");
exit(1);
}
else if (pid == 0) // 子进程
{
strcpy(p, "hello mmap_anon");
printf("子进程完成写共享内存操作(匿名映射)\n");
}
else // 父进程
{
sleep(1); // 睡眠一秒,让子进程完成写共享内存操作
printf("%s\n", p);
printf("父进程完成读共享内存操作(匿名映射)\n");
}
// 系统调用删除指定地址范围的映射
if(munmap(p, n) == -1)
{
perror("mumap faild");
exit(1);
}
return 0;
}
类UNIX
MAP_ANONYMOUS 和 MAP_ANON 这两个宏是 Linux 操作系统特有的宏。在类 Unix 系统中如无该宏定义,可通过/dev/zero文件完成匿名映射。
示例
/*
* function: 演示使用mmap()函数实现使用共享映射区完成父子进程间通信
*
* 2020-12-07
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
int main(int argc, char *argv[])
{
// 打开一个文件
int fd = open("/dev/zero", O_RDWR);
if (fd == -1)
{
perror("open faild");
exit(1);
}
// 将文件映射到共享内存中
char *p = NULL;
size_t n = 10;
p = (char *)mmap(NULL, n, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (p == MAP_FAILED)
{
perror("mmap failed");
exit(1);
}
pid_t pid = 0;
pid = fork();
if (pid == -1)
{
perror("fork faild");
exit(1);
}
else if (pid == 0) // 子进程
{
strcpy(p, "hello mmap_anon_unix");
printf("子进程完成写共享内存操作(匿名映射)\n");
}
else // 父进程
{
sleep(1); // 睡眠一秒,让子进程完成写共享内存操作
printf("%s\n", p);
printf("父进程完成读共享内存操作(匿名映射)\n");
}
// 系统调用删除指定地址范围的映射
if(munmap(p, n) == -1)
{
perror("mumap faild");
exit(1);
}
close(fd);
return 0;
}