共享内存是通信效率最高的IPC方式,因为进程可以直接读写内存,而无需进行数据的拷备。但是它没有自带同步机制,需要配合信号量等方式来进行同步。
共享内存被创建以后,同一块物理内存被映射到了多个进程地址空间,当有一个进程修改了共享内存的数据,其余的进程均可看见所修改的内容,反之亦然。
mmap函数
函数原型:
- void mmap(void adrr, size_t length, int prot, int flags, int fd, off_t offset);
返回值:
- 成功:返回创建的映射区首地址;
- 失败:返回MAP_FAILED
具体参数含义:
- addr:指向映射区的首地址,这是由系统内核所决定的,一般设为NULL;
- length:欲创建的映射区大小;
- prot:映射区的权限,一般有如下几种:
- PROT_EXEC 映射区域可被执行
- PROT_READ 映射区域可被读取
- PROT_WRITE 映射区域可被写入
- PROT_NONE 映射区域不能存取
- flags:指映射区的标志位,MAP_FIXED与MAP_PRIVATE必须选择一个:
- MAP_FIXED:对映射区所作的修改会反映到物理设备,但需要调用msync()或者munmap();
- MAP_PRIVATE:对映射区所作的修改不会反映到物理设备。
- fd:创建的映射区的文件描述符;
- offset:被映射文件的偏移量,一般设为0,表示从头开始映射。
mumap函数
函数原型:
- int munmap(void *addr, size_t length);
函数作用:
如同malloc之后需要free一样,mmap调用创建的映射区使用完毕之后,需要调用munmap去释放。
例程
写进程:
- #include <stdio.h>
- #include <sys/mman.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <string.h>
-
- typedef struct
- {11 int id;
- char name[20];
- char gender;
- }stu;
-
- int main(int argc, char *argv[])
- {
- stu *p = NULL;
- int fd = 0;
- stu student = {10, "harry", 'm'};
-
- if (argc < 2) {
- printf("useage: ./a.out file\n");
- return -1;
- }
-
- fd = open(argv[1], O_RDWR | O_CREAT, 0664);
- if (fd == -1) {
- printf("ERROR: open failed!\n");
- return -1;
- }
- ftruncate(fd, sizeof(stu));
-
- p = mmap(NULL, sizeof(stu), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if (p == MAP_FAILED) {
- printf("ERROR: mmap failed!\n");
- return -1;
- }
-
- close(fd);
-
- while (1) {
- memcpy(p, &student, sizeof(stu));
- student.id++;
- sleep(2);
- }
- munmap(p, sizeof(stu));
-
- return 0;
- }
读进程:
- #include <stdio.h>
- #include <sys/mman.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
-
- typedef struct
- {
- int id;
- char name[20];
- char gender;
- }stu;
-
- int main(int argc, char *argv[])
- {
- stu *p = NULL;
- int fd = 0;
-
- if (argc < 2) {
- printf("useage: ./a.out file\n");
- return -1;
- }
-
- fd = open(argv[1], O_RDONLY);
- if (fd == -1) {
- printf("ERROR: open failed!\n");
- return -1;
- }
-
- p = mmap(NULL, sizeof(stu), PROT_READ, MAP_SHARED, fd, 0);
- if (p == MAP_FAILED) {
- printf("ERROR: mmap failed!\n");
- return -1;
- }
-
- close(fd);
-
- while (1) {
- printf("id = %d, name = %s, gender = %c\n", p->id, p->name, p->gender);
- sleep(2);
- }
-
- munmap(p, sizeof(stu));
-
- return 0;
- }
本文授权转载自公众号「良许Linux」。良许,世界500强外企Linux开发工程师,公众号里分享大量Linux干货,欢迎关注!