热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

linuxipc——sharedmemory

1、概念共享内存:共享内存是进程间通信中最简单的方式之一。共享内存允许两个或更多进程访问同一块内存,就如同malloc()函数向不同进程返回了指向同一个

1、概念

共享内存:共享内存是进程间通信中最简单的方式之一。共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针。当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改。

2、用途

. 共享内存允许两个或多个进程共享一给定的存储区,因为数据不需要来回复制,所以是最快的一种进程间通信机制。共享内存可以通过mmap()映射普通文件(特殊情况下还可以采用匿名映射)机制实现,也可以通过系统V共享内存机制实现。应用接口和原理很简单,内部机制复杂。为了实现更安全通信,往往还与信号灯等同步机制共同使用

  共享内存涉及到了存储管理以及文件系统等方面的知识,深入理解其内部机制有一定的难度,关键还要紧紧抓住内核使用的重要数据结构。系统V共享内存是以文件的形式组织在特殊文件系统shm中的。通过shmget可以创建或获得共享内存的标识符。取得共享内存标识符后,要通过shmat将这个内存区映射到本进程的虚拟地址空间

3、特点

共享内存。顾名思义,这种通信方式允许多个进程共享同一块物理内存空间来实现进程之间的信息交换,其特点是没有中间环节,直接将共享的内存页面通过附接,映射到相互通信的进程各自的虚拟地址空间中,从而使多个进程可以直接访问同一个物理内存页面,如同访问自己的私有空间一样(但实质上不是私有的而是共享的)。因此这种进程间通信方式是在同一个计算机系统中的诸进程间实现通信的最快捷的方法,而它的局限性也在于此,即共享内存的诸进程必须共处同一个计算机系统,有物理内存可以共享才行。

4、用法:

发送进程:
1.使用系统调用函数shmget()创建或者获取指定key值的共享内存;
2.使用系统调用函数shmat(),将该共享内存附接到自己的虚拟地址空间;
3.将需要发送的信息写入共享内存,方法有以下几种:
①.每条信息都以追加的方式写入,可以使用C语言提供的字符串追加函数strcat(viraddr, buffer),该函数的功能是将buffer中的字符串追加到由viraddr附接的共享存储区的尾部。其中,viraddr是请求得到的共享内存的地址,buffer是用户进程中请求的用来存放信息的字符缓冲区。
②.每条信息都以覆盖的方式写入,可以使用strcpy(viraddr,buffer)函数将buffer中的字符串复制到viraddr指向的共享内存中,则该共享内存中就只有当前复制进来的信息,以前复制的信息被覆盖了。
③.共享内存定义为数值型变量,则可以将*viraddr作为数值型变量对其进行操作。例如将其赋值为0可以使用:*viradd=0。
④.共享内存定义为数值型数组,则可以将viraddr[i]作为下标变量使用。例如将其赋值为0可以使用: viradd[i]=0。
4.使用系统调用函数shmdt(),断开共享内存。

 

接收进程:
    1.  用系统调用函数shmget();创建或者获取指定key值的共享内存;
    2.  用系统调用函数shmat();将该共享内存附接到自己的程序空间;
    3.将共享内存中的信息输出;或取出存放到其它数据块中;
    4.使用系统调用函数shmdt();断开共享内存。
    5.如果不再使用共享内存时,使用系统调用函数shmctl()将其撤消,格式为:shmctl(shmid,IPC_RMID,0);

获得一个共享存储标识符
 #include
 #include
 int shmget(key_t key, size_t size,intshmflg);
 功能:创建或打开一块共享内存区
 参数:
     key:IPC键值
     size:该共享存储段的长度(字节)
     shmflg:用来标识函数的行为

参数:
shmflg:用来标识函数的行为
 IPC_CREAT:如果不存在就创建
 IPC_EXCL:如果已经存在则返回失败
 IPC_NOWAIT:调用进程会立即返回。若发生错误则返回-1。
SHM_R:可读
SHM_W:可写
返回值:
成功:返回共享内存标识符。
失败:返回-1。

 

共享内存映射(attach)
 #include
 #include
 void *shmat(int shmid, const void *shmaddr,
       int shmflg);
 功能:
     将一个共享内存段映射到调用进程的数据段中。
 参数:
     shmid:共享内存标识符。
     shmaddr:共享内存映射地址(若为NULL则由系      统自动指定),推荐使用NULL。

参数:
 shmflg:共享内存段的访问权限和映射条件
0:共享内存具有可读可写权限。
SHM_RDONLY:只读。
SHM_RND:(shmaddr非空时才有效)
    没有指定SHM_RND则此段连接到shmaddr所指定的地址上(shmaddr必需页对齐)。
    指定了SHM_RND则此段连接到shmaddr- shmaddr%SHMLAB 所表示的地址上。
返回值:
成功:返回共享内存段首地址
失败:返回 -1

 

解除共享内存映射(detach)
 #include
 #include
 int shmdt(const void *shmaddr);
 功能:
       将共享内存和当前进程分离(仅仅是断开联系并不删除共享内存)。
 参数:
shmaddr:共享内存映射地址。
 返回值:
成功返回 0,失败返回 -1。

 

#include
 #include
 int shmctl(int shmid, int cmd,
       struct shmid_ds *buf);
 功能:共享内存空间的控制。
 参数:
shmid:共享内存标识符。
cmd:函数功能的控制。
buf:shmid_ds数据类型的地址,用来存放或更改消息队列的属性。

参数:
cmd:函数功能的控制
IPC_RMID:删除。
IPC_SET:设置shmid_ds参数。
IPC_STAT:保存shmid_ds参数。
SHM_LOCK:锁定共享内存段(超级用户)。
SHM_UNLOCK:解锁共享内存段。
返回值:
     成功返回 0,失败返回 -1。

5、案例

读:

#include
#include
#include
#include
#include
#include
#include

#define BUFSZ 2048

int main(int argc, char *argv[])
{
 int shmid;
 int ret;
 key_t key;
 char *shmadd;
 
 key = ftok(".", 2012);
 if(key==-1)
 {
  perror("ftok");
 }
 system("ipcs -m");
 /*打开共享内存*/
 shmid = shmget(key, BUFSZ, SHM_R|SHM_W); 
 if(shmid <0)
 {
  perror("shmget");
  exit(-1);
 }
 /*映射*/
 shmadd &#61; shmat(shmid, NULL, 0);
 if(shmadd <0)
 {
  perror("shmat");
  exit(-1);
 }
 /*读共享内存区数据*/
 printf("copy data from shared-memory\n");
 printf("data &#61; [%s]\n", shmadd);
 /*分离共享内存和当前进程*/
 ret &#61; shmdt(shmadd);
 if(ret <0)
 {
  perror("shmdt");
  exit(1);
 }
 else
 {
  printf("deleted shared-memory\n");
 }
 /*删除共享内存*/
 shmctl(shmid, IPC_RMID, NULL);
 system("ipcs -m");
 return 0;
}

写&#xff1a;

#include
#include
#include
#include
#include
#include
#include

#define BUFSZ 2048

int main(int argc, char *argv[])
{
 int shmid;
 int ret;
 key_t key;
 char *shmadd;
 
 key &#61; ftok(".", 2012);
 if(key &#61;&#61; -1)
 {
  perror("ftok");
 }
 /*创建共享内存*/
 shmid &#61; shmget(key, BUFSZ, SHM_R|SHM_W|IPC_CREAT); 
 if(shmid <0)
 {
  perror("shmget");
  exit(-1);
 }
 /*映射*/
 shmadd &#61; shmat(shmid, NULL, 0);
 if(shmadd <0)
 {
  perror("shmat");
  _exit(-1);
 }
 /*拷贝数据至共享内存区*/
 printf("copy data to shared-memory\n");
 bzero(shmadd, BUFSZ);
 strcpy(shmadd, "data in shared memory\n");
 return 0;
}

 

转:https://www.cnblogs.com/kunyashaw/archive/2013/06/05/3119406.html



推荐阅读
  • 题目描述:计算从起点到终点的最小能量消耗。如果下一个单元格的风向与当前单元格相同,则消耗为0,否则为1。共有8个可能的方向。 ... [详细]
  • 编译原理中的语法分析方法探讨
    本文探讨了在编译原理课程中遇到的复杂文法问题,特别是当使用SLR(1)文法时遇到的多重规约与移进冲突。文章讨论了可能的解决策略,包括递归下降解析、运算符优先级解析等,并提供了相关示例。 ... [详细]
  • 大华股份2013届校园招聘软件算法类试题D卷
    一、填空题(共17题,每题3分,总共51分)1.设有inta5,*b,**c,执行语句c&b,b&a后,**c的值为________答:5 ... [详细]
  • 开发笔记:1035 Password (20) ... [详细]
  • 优先队列是一种特殊的队列,不遵循先进先出原则。它分为最大优先队列和最小优先队列。最大优先队列总是将当前最大的元素优先出队,而最小优先队列则总是将当前最小的元素优先出队。本文将详细介绍如何使用二叉堆在C#中实现这两种优先队列。 ... [详细]
  • 用C语言实现的科学计算器,支持2种常量,10种基本函数,Ans寄存器。相对来说拓展性应该是不错的,思路是首先化简复杂名称的函 ... [详细]
  • ipsec 加密流程(二):ipsec初始化操作
    《openswan》专栏系列文章主要是记录openswan源码学习过程中的笔记。Author:叨陪鲤Email:vip_13031075266163.comDate:2020.1 ... [详细]
  • 本文详细介绍了 Java 中 org.w3c.dom.Node 类的 isEqualNode() 方法的功能、参数及返回值,并通过多个实际代码示例来展示其具体应用。此方法用于检测两个节点是否相等,而不仅仅是判断它们是否为同一个对象。 ... [详细]
  • 本文介绍了实时流协议(RTSP)的基本概念、组成部分及其与RTCP的交互过程,详细解析了客户端请求格式、服务器响应格式、常用方法分类及协议流程,并提供了SDP格式的深入解析。 ... [详细]
  • UVa 1579 - 套娃问题
    本题主要涉及动态规划(DP)的应用,通过计算将前i个套娃合并成多个套娃组所需的最小操作次数来解决问题。具体来说,f(i) 表示前i个套娃合并成多个套娃组所需的操作次数,其计算公式为 f(i) = min(f(j) + dp(j+1, i))。 ... [详细]
  • mysql数据库json类型数据,sql server json数据类型
    mysql数据库json类型数据,sql server json数据类型 ... [详细]
  • 本文探讨了在UIScrollView上嵌入Webview时遇到的一个常见问题:点击图片放大并返回后,Webview无法立即滑动。我们将分析问题原因,并提供有效的解决方案。 ... [详细]
  • C语言中的指针详解
    1.什么是指针C语言中指针是一种数据类型,指针是存放数据的内存单元地址。计算机系统的内存拥有大量的存储单元,每个存储单元的大小为1字节, ... [详细]
  • RTThread线程间通信
    线程中通信在裸机编程中,经常会使用全局变量进行功能间的通信,如某些功能可能由于一些操作而改变全局变量的值,另一个功能对此全局变量进行读取& ... [详细]
  • 本文详细探讨了Spring框架中遇到的NoSuchBeanDefinitionException异常,具体涉及com.thinkplatform.dao.UserLogDao Bean未定义的问题,并提供了相应的解决方案。 ... [详细]
author-avatar
吴由兴_834
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有