共享内存
最为高效的进程间通信方式
进程直接读写内存,不需要任何数据的拷贝
•为了在多个进程间交换信息,内核专门留出了一块内存区
•由需要访问的进程将其映射到自己私有地址空间
•进程直接读写这一内存区而不需要进行数据的拷贝,提高了效率
多个进程共享一段内存,需要依靠某种同步机制,如互斥锁和信号量等
l共享内存编程步骤:
1. 创建共享内存
•函数shmget()
•从内存中获得一段共享内存区域
2. 映射共享内存
•把这段创建的共享内存映射到具体的进程空间中
•函数shmat()
3. 使用这段共享内存
•可以使用不带缓冲的I/O读写命令对其进行操作
4. 撤销映射操作: 函数shmdt()
5. 删除共享内存: 函数shctl()
下面这个例子完成:父进程从stdin读取字符串并保存到共享内存中,子进程从共享内存中读出数据并输出到stdout
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/shm.h>
-
- #define BUFFER_SIZE 2048
-
- int main() {
- pid_t pid;
- int shmid;
- char *shm_addr;
- char flag[]="Parent";
- char buff[BUFFER_SIZE];
- // 创建当前进程的私有共享内存
- if ((shmid=shmget(IPC_PRIVATE,BUFFER_SIZE,0666))<0) {
- perror("shmget");
- exit(1);
- } else
- printf("Create shared memory: %d.\n",shmid);
-
- // ipcs 命令往标准输出写入一些关于活动进程间通信设施的信息
- // -m 表示共享内存
- printf("Created shared memory status:\n");
- system("ipcs -m");
-
- if((pid=fork())<0) {
- perror("fork");
- exit(1);
- }else if (pid==0) {
- // 自动分配共享内存映射地址,为可读可写,映射地址返回给shm_addr
- if ((shm_addr=shmat(shmid,0,0))==(void*)-1) {
- perror("Child:shmat");
- exit(1);
- }else
- printf("Child: Attach shared-memory: %p.\n",shm_addr);
-
- printf("Child Attach shared memory status:\n");
- system("ipcs -m");
- // 比较shm_addr,flag的长度为strlen(flag)的字符
- // 当其内容相同时,返回0
- // 否则返回(str1[n]-str2[n])
- while (strncmp(shm_addr,flag,strlen(flag))) {
- printf("Child: Waiting for data...\n");
- sleep(10);
- }
-
- strcpy(buff,shm_addr+strlen(flag));
- printf("Child: Shared-memory: %s\n",buff);
- // 删除子进程的共享内存映射地址
- if (shmdt(shm_addr)<0) {
- perror("Child:shmdt");
- exit(1);
- }else
- printf("Child: Deattach shared-memory.\n");
-
- printf("Child Deattach shared memory status:\n");
- system("ipcs -m");
-
- }else{
- sleep(1);
- // 自动分配共享内存映射地址,为可读可写,映射地址返回给shm_addr
- if ((shm_addr=shmat(shmid,0,0))==(void*)-1) {
- perror("Parent:shmat");
- exit(1);
- }else
- printf("Parent: Attach shared-memory: %p.\n",shm_addr);
-
- printf("Parent Attach shared memory status:\n");
- system("ipcs -m");
- // shm_addr为flag+stdin
- sleep(1);
- printf("\nInput string:\n");
- fgets(buff,BUFFER_SIZE-strlen(flag),stdin);
- strncpy(shm_addr+strlen(flag),buff,strlen(buff));
- strncpy(shm_addr,flag,strlen(flag));
- // 删除父进程的共享内存映射地址
- if (shmdt(shm_addr)<0) {
- perror("Parent:shmdt");
- exit(1);
- }else
- printf("Parent: Deattach shared-memory.\n");
-
- printf("Parent Deattach shared memory status:\n");
- system("ipcs -m");
- // 保证父进程在删除共享内存前,子进程能读到共享内存的内容
- waitpid(pid,NULL,0);
- // 删除共享内存
- if (shmctl(shmid,IPC_RMID,NULL)==-1) {
- perror("shmct:IPC_RMID");
- exit(1);
- }else
- printf("Delete shared-memory.\n");
-
- printf("Child Delete shared memory status:\n");
- system("ipcs -m");
-
- printf("Finished!\n");
- }
-
- exit(0);
- }
执行结果:
阅读(1125) | 评论(0) | 转发(0) |