linux进程通信----共享内存
来源:互联网 发布:知乎立升净水器好不好 编辑:程序博客网 时间:2024/05/17 07:31
共享内存是一种最为高效的进程间通信方式,因为进程可以直接读写内存,不需要任何数据的复制,为了在多个进程间交换信息,内核专门留出了一块内存区,这块内存进程可以直接将其映射到进程的私有空间中,可以直接读写,所以大大提高了效率,由于多个进程共享一个内存区,所以需要依靠某种同步机制,例如信号量,互斥锁等。
共享内存原理示意图:
实现共享内存有三个步骤:
- 创建共享内存,使用shmget(),也就是从内存中获取一段共享内存区域
- 映射共享内存,把创建的共享内存映射到具体的进程空间中,使用函数shmat(),现在就可以使用共享内存了,可以使用不带缓冲的的I/O读写命令对其进行操作
- 撤销映射的操作,使用shmdt()函数即可
shmget()的函数语法格式:
shmat()函数语法如下:
shmdt语法如下:
这里需要补充一个删除共享内存的函数shmctl()
#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#define BUFFER_SIZE 2048int main(){ pid_t pid ; int shmid ; char *shm_addr ; char flag[] = "WROTE" ; char *buff ; //创建共享内存 if ((shmid = shmget(IPC_PRIVATE, BUFFER_SIZE, 0666)) < 0) { perror("shmget") ; exit(1) ; } else { printf("create shared-memory:%d\n", shmid) ; } system("ipcs -m") ;//通过ipcs -m获取共享内存的信息 pid = fork() ; if (pid == -1) { perror("fork") ; exit(1) ; } else if (pid == 0) { //shm_addr是传回来的映射地址,判断其是否等于(void *)-1??? if ((shm_addr = shmat(shmid, 0, 0)) == (void *)-1) { perror("child:shmat") ; exit (1) ; } else { printf("child:attach shared memeory:%p\n", shm_addr) ; } system("ipcs -m") ;//子进程映射之后查看共享内存的状态 /*通过查看共享内存是否含有flag,如果有表示父进程已经向共享内存中 写入了数据,以此做了一个简单的同步的工作*/ while(strncmp(shm_addr, flag, strlen(flag))) { printf("child:wait for enable data...\n") ; sleep(5) ; } strcpy(buff, shm_addr + strlen(flag)) ; printf("child:shared-memory:%s\n", buff) ; if ((shmdt(shm_addr)) < 0)//撤销映射 { perror("shmdt") ; exit(1) ; } else { printf("child:deattach shared-memory\n") ; } system("ipcs -m") ;//撤销映射之后共享内存的状态 if (shmctl(shmid, IPC_RMID, NULL) == -1)//删除共享内存 { perror("shmctl") ; exit(1) ; } else { printf("delete shared-memory\n") ; } system("ipcs -m") ;//删除共享内存之后,查看共享内存的状态 } else { if ((shm_addr = shmat(shmid, 0, 0)) == (void *) - 1)//父进程映射内存 { perror("shmat") ; exit(1) ; } else { printf("parent: attach shared-memory:%p\n", shm_addr) ; } sleep(1) ; printf("\ninput some string\n") ; fgets(buff, BUFFER_SIZE, stdin) ;//从标准输入中提取BUFFER_SIZE个字符 strncpy(shm_addr + strlen(flag), buff, strlen(buff)) ;//向共享内存中写入 strncpy(shm_addr, flag, strlen(flag)) ; if (shmdt(shm_addr) < 0)//解除映射 { perror("shmdt") ; exit(1) ; } else { printf("deatch shared-memory\n") ; } system("ipcs -m") ; waitpid(pid, NULL, 0) ;//等待子进程结束 printf("finished\n") ; } exit(0) ;}创建共享内存时我们指定键值为IPC_PRIVATE,用于创建当前进程的私有共享内存,这个例子中创建的共享内存是父子进程之间的共用部分,所以指定了IPC_PRIVATE
可以看一下运行结果:
在创建共享内存时:
父子进程分别作了映射:
此时看共享内存的状态:
然后我们向共享内存输入一个字符串"zhang",子进程将会读出这个字符串,然后父子进程分别解除映射
最后子进程删除共享内存,此时将查看不到共享内存.
因为共享内存是这里使用一个标志字符串作为同步的标志
这里有个问题弄不懂:
共享内存需要互斥访问,父子进程是怎么同步的?
子进程:while(strncmp(shm_addr, flag, strlen(flag))) { printf("child:wait for enable data...\n") ; sleep(5) ; }
父进程:
printf("\ninput some string\n") ; fgets(buff, BUFFER_SIZE, stdin) ;//从标准输入中提取BUFFER_SIZE个字符 strncpy(shm_addr + strlen(flag), buff, strlen(buff)) ;//向共享内存中写入 strncpy(shm_addr, flag, strlen(flag)) ;父子进程都对共享内存进行了操作,那怎么互斥访问呢?
- linux进程通信-共享内存
- Linux 进程通信--共享内存
- Linux 进程通信--共享内存
- Linux 进程通信--共享内存。
- Linux 进程通信--共享内存
- linux进程通信--共享内存
- linux进程通信----共享内存
- linux进程通信-共享内存
- Linux进程通信--共享内存
- Linux进程通信-共享内存
- Linux进程通信共享内存
- linux进程通信--共享内存
- linux进程通信--共享内存
- linux进程通信-共享内存
- LINUX进程通信,共享内存
- Linux进程通信共享内存
- Linux环境进程间通信: 共享内存
- Linux环境进程间通信:共享内存
- 实战做项目如何选择开源许可协议(一)
- Android学习笔记7:四大组件之ContentProvider
- Unity3D 学习笔记(一)
- EXTJS4.x之实战项目(5)ArticleGridPanel实现增删改查之增
- 如何正确的打开google
- linux进程通信----共享内存
- 两个控制器之间的数据传递 (MVC)
- 典型背包问题
- PhotoShop算法原理解析系列
- 【转】XP/Win7/Vista和Linux(Ubuntu\fedora等)双系统下完美卸载Linux
- 判断字符串是不是数字的三种方法
- vi 复制粘贴详解
- [珠玑之椟]二分思想与分治法、排序思想
- spring配置连接数据库