linux 共享内存(转)
2014-10-22 00:00
477 查看
摘要: linux 共享内存
可以说,共享内存是一种最为高效的进程间通信方式,因为进程可以直接读写内存,不需要任何数据的复制。为了在多个进程间交换信息,内核专门留出了一 块内存区,这段内存区可以由需要访问的进程将其映射到自己的私有地址空间。因此,进程就可以直接读写这一内存区而不需要进行数据的复制,从而大大提高了效 率。当然,由于多个进程共享一段内存,因此也需要依靠某种同步机制,如互斥锁和信号量等。其原理示意图如图1所示。
图1 共享内存原理示意图
共享内存的实现分为两个步骤:第一步是创建共享内存,这里用到的函数是shmget(),也就是从内存中获得一段共享内存区域;第 二步是映射共享内存,也就是把这段创建的共享内存映射到具体的进程空间中,这里使用的函数是shmat()。到这里,就可以使用这段共享内存了,也就是可 以使用不带缓冲的I/O读写命令对其进行操作。除此之外,还有撤销映射的操作,其函数为shmdt()。这里主要介绍这3个函数。
表1 列举了shmget()函数的语法要点。
以下实例说明了如何使用基本的共享内存函数。首先创建一个共享内存区(采用的共享内存的键值为IPC_PRIVATE,是因为本实例中创建的共享内存是父子进程间的共用部分),然后创建子进程,在父子两个进程中将共享内存分别映射到各自的进程地址空间中。
父进程先等待用户输入,然后将用户输入的字符串写入到共享内存,之后向共享内存的头部写入“WROTE”字符串表示父进程已成功写 入数据。子进程一直等到共享内存的头部字符串为“WROTE”,然后将共享内存的有效数据(在父进程中用户输入的字符串)在屏幕上打印。父子两个进程在完 成以上工作后,分别解除与共享内存的映射关系。
最后在子进程中删除共享内存。因为共享内存自身并不提供同步机制,所以应额外实现不同进程间的同步(如信号量)。为了简单起见,在本实例中用标志字符串来实现非常简单的父子进程间的同步。
这里要介绍的一个命令是ipcs,用于报告进程间通信机制状态,它可以查看共享内存、消息队列等各种进程间通信机制的情况,这里使用了system()函数调用shell命令“ipcs”。程序源代码如下:
下面是运行结果,从该结果中可以看出,nattch的值随着共享内存状态的变化而变化,共享内存的值根据不同的系统会有所不同。
转载于:
linux 共享内存
可以说,共享内存是一种最为高效的进程间通信方式,因为进程可以直接读写内存,不需要任何数据的复制。为了在多个进程间交换信息,内核专门留出了一 块内存区,这段内存区可以由需要访问的进程将其映射到自己的私有地址空间。因此,进程就可以直接读写这一内存区而不需要进行数据的复制,从而大大提高了效 率。当然,由于多个进程共享一段内存,因此也需要依靠某种同步机制,如互斥锁和信号量等。其原理示意图如图1所示。
图1 共享内存原理示意图
共享内存的实现分为两个步骤:第一步是创建共享内存,这里用到的函数是shmget(),也就是从内存中获得一段共享内存区域;第 二步是映射共享内存,也就是把这段创建的共享内存映射到具体的进程空间中,这里使用的函数是shmat()。到这里,就可以使用这段共享内存了,也就是可 以使用不带缓冲的I/O读写命令对其进行操作。除此之外,还有撤销映射的操作,其函数为shmdt()。这里主要介绍这3个函数。
表1 列举了shmget()函数的语法要点。
以下实例说明了如何使用基本的共享内存函数。首先创建一个共享内存区(采用的共享内存的键值为IPC_PRIVATE,是因为本实例中创建的共享内存是父子进程间的共用部分),然后创建子进程,在父子两个进程中将共享内存分别映射到各自的进程地址空间中。
父进程先等待用户输入,然后将用户输入的字符串写入到共享内存,之后向共享内存的头部写入“WROTE”字符串表示父进程已成功写 入数据。子进程一直等到共享内存的头部字符串为“WROTE”,然后将共享内存的有效数据(在父进程中用户输入的字符串)在屏幕上打印。父子两个进程在完 成以上工作后,分别解除与共享内存的映射关系。
最后在子进程中删除共享内存。因为共享内存自身并不提供同步机制,所以应额外实现不同进程间的同步(如信号量)。为了简单起见,在本实例中用标志字符串来实现非常简单的父子进程间的同步。
这里要介绍的一个命令是ipcs,用于报告进程间通信机制状态,它可以查看共享内存、消息队列等各种进程间通信机制的情况,这里使用了system()函数调用shell命令“ipcs”。程序源代码如下:
/* shmem.c */ #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"); pid = fork(); if (pid == -1) { perror("fork"); exit(1); } else if (pid == 0) /* 子进程处理 */ { /* 映射共享内存 */ if ((shm_addr = shmat(shmid, 0, 0)) == (void*)-1) { perror("Child: shmat"); exit(1); } else { printf("Child: Attach shared-memory: %p\n", shm_addr); } system("ipcs -m"); /* 通过检查在共享内存的头部是否有标志字符串“WROTE”来确认父进程已经向共享内存写入有效数据 */ 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("Child: shmctl(IPC_RMID)\n"); exit(1); } else { printf("Delete shared-memory\n"); } system("ipcs -m"); } else /* 父进程处理 */ { /* 映射共享内存 */ if ((shm_addr = shmat(shmid, 0, 0)) == (void*)-1) { perror("Parent: 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); 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"); } system("ipcs -m"); waitpid(pid, NULL, 0); printf("Finished\n"); } exit(0); }
下面是运行结果,从该结果中可以看出,nattch的值随着共享内存状态的变化而变化,共享内存的值根据不同的系统会有所不同。
$ ./shmem Create shared-memory: 753665 /* 在刚创建共享内存时(尚未有任何地址映射)共享内存的情况 */ ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 753665 david 666 2048 0 Child: Attach shared-memory: 0xb7f59000 /* 共享内存的映射地址 */ Parent: Attach shared-memory: 0xb7f59000 /* 在父子进程中进行共享内存的地址映射后共享内存的情况 */ ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 753665 david 666 2048 2 Child: Wait for enable data... Input some string: Hello /* 用户输入字符串“Hello” */ Parent: Deattach shared-memory /* 在父进程中解除共享内存的映射关系后共享内存的情况 */ ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 753665 david 666 2048 1 /* 在子进程中读取共享内存的有效数据并打印 */ Child: Shared-memory :hello Child: Deattach shared-memory /* 在子进程中解除共享内存的映射关系后共享内存的情况 */ ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 753665 david 666 2048 0 Delete shared-memory /* 在删除共享内存后共享内存的情况 */ ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status Finished
转载于:
linux 共享内存
相关文章推荐
- Linux环境进程间通信: 共享内存
- Linux环境进程间通信:共享内存
- Linux环境进程间通信(五): 共享内存(下)
- Linux环境进程间通信(五): 共享内存(上)
- Linux环境进程间通信 共享内存
- Linux环境进程间通信(五): 共享内存(下)
- 将 Win32 C/C++ 应用程序迁移到 POWER 上的 Linux,第 1 部分: 进程、线程和共享内存服务 (转载)
- Linux编程常用的函数(五) 共享内存
- Linux环境进程间通信(五): 共享内存(下)
- Linux中共享内存及内存映射技术
- linux-c: ipc_共享内存
- Linux中共享内存及内存映射技术研究
- Linux的共享内存技术
- Linux环境进程间通信(五): 共享内存(上)
- linux 文件操作函数 通过例子来解释 父子间文件描述符共享 内存映像图
- Linux环境进程间通信:共享内存
- Linux中共享内存及内存映射技术研究
- Linux环境进程间通信: 共享内存
- Linux环境进程间通信(五): 共享内存(上)
- 将 Win32 C/C++ 应用程序迁移到 POWER 上的 Linux,第 1 部分: 进程、线程和共享内存服务 (转)