linux进程通信----共享内存
2013-07-06 14:08
465 查看
共享内存是一种最为高效的进程间通信方式,因为进程可以直接读写内存,不需要任何数据的复制,为了在多个进程间交换信息,内核专门留出了一块内存区,这块内存进程可以直接将其映射到进程的私有空间中,可以直接读写,所以大大提高了效率,由于多个进程共享一个内存区,所以需要依靠某种同步机制,例如信号量,互斥锁等。
共享内存原理示意图:
实现共享内存有三个步骤:
创建共享内存,使用shmget(),也就是从内存中获取一段共享内存区域
映射共享内存,把创建的共享内存映射到具体的进程空间中,使用函数shmat(),现在就可以使用共享内存了,可以使用不带缓冲的的I/O读写命令对其进行操作
撤销映射的操作,使用shmdt()函数即可
shmget()的函数语法格式:
shmat()函数语法如下:
shmdt语法如下:
这里需要补充一个删除共享内存的函数shmctl()
可以看一下运行结果:
在创建共享内存时:
父子进程分别作了映射:
此时看共享内存的状态:
然后我们向共享内存输入一个字符串"zhang",子进程将会读出这个字符串,然后父子进程分别解除映射
最后子进程删除共享内存,此时将查看不到共享内存.
因为共享内存是这里使用一个标志字符串作为同步的标志
这里有个问题弄不懂:
共享内存需要互斥访问,父子进程是怎么同步的?
子进程:
父进程:
共享内存原理示意图:
实现共享内存有三个步骤:
创建共享内存,使用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 2048 int 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进程间共享内存通信详解
- 进程通信之内存地址映射与共享,同时如何在Linux0.11下实现共享内存
- linux 进程通信之共享内存
- linux基础编程:进程通信之System V IPC:消息队列,信号量,共享内存
- linux进程间的通信: 共享内存
- linux进程通信-共享内存
- Linux下进程通信之共享内存
- Linux\Unix IPC进程通信实例分析(一):共享内存通信---系统V
- linux进程通信IPC之共享内存的IPC_PRIVATE与ftok比较
- linux进程间的通信(C): 共享内存
- Linux进程通信-共享内存
- linux下进程间共享内存通信的问题
- Linux C程序练习(4)进程通信之信号量、共享内存
- Linux进程间的通信方式:共享内存的使用
- linux下通过共享内存在进程之间实现通信(system V)
- linux进程间共享内存通信详解