`
tomotoboy
  • 浏览: 167282 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

进程间通信——共享内存

阅读更多
共享内存(Shared Memory)
共享内存,简单的说就是被多个进程共享的内存。它在各种进程通信方法中是最快的,因为它是将信息直接映射到内存中,

省去了其它 IPC方法的中间步骤。
1.shmid_ds
共享内存也有一个给系统内存用来保存相关信息的机构,就是shmid_ds。
struct shmid_ds{
struct ipc_perm shm_perm;  	             //operation
int		shm_segsz;            //size of segment
_kernel_time_t	shm_atime;            //last attach time
_kernel_time_t	shm_dtime;            //last detach time	
_kernel_time_t	shm_ctime;            //last change time
_kernel_ipc_pid_t	shm_cpid;     //pid of creator
_kernel_ipc_pid_t	shm_lpid      //pid of last operator
unsigned short		shm_nattch;   //no. of current attaches
unsigned short		shm_unused;   //compatibility
void			*shm_unused2; //ditto - used by DIPC
void			*shm_unused3; //unused
}


其中:
shm_perm    成员储存了共享内存对象的存取权限及其它一些信息。
shm_segsz   成员定义了共享的内存大小(以字节为单位)。
shm_atime   成员保存了最近一次进程连接共享内存的时间。
shm_dtime   成员保存了最近一次进程断开与共享内存的连接的时间。
shm_ctime   成员保存了最近一次 shmid_ds 结构内容改变的时
shm_cpid     成员保存了创建共享内存的进程的 pid。
shm_lpid      成员保存了最近一次连接共享内存的进程的 pid。
shm_nattch  成员保存了与共享内存连接的进程数目。
剩下的三个成员被内核保留使用,这里就不介绍了。

有关的函数
1、sys_shmget()函数
使用shmget()函数来创建新的获取得已有的共享内存。
系统调用:shmget()
函数声明:int shmget(key_t key,int size,int shmflg);
    返回值:shared memory segment identigier on success
                 -1 on error: errno =

shmget()函数的第一个参数key 是共享内存的关键字;第二个参数 size 是创建的共享内存的大小,以字节为单位。第三个参

数 shmflg 是控制函数行为的标志量,其取值的含义和作用和 msgget()及semget()函数的对应参数都是相同的.

int open_shm(key_t keyval, int segsize)
{
	int shmid;
	if(shmid=shmget(keyval, segsize,IPC_CREAT|0660))==-1)
	{
		return(-1);
	}
	return(shmid);
}


2、shmat()函数
当一个进程使用 shmget()函数得到了共享内存的标识符之后,就可以使用shmat()函数来将共享内存映射到进程自己的内

存空间内。
系统调用:shmat()
函数声明: int shmat(int shmid, char *shmaddr, int shmflg);
    返回值: address at which segment was attached to the process, or
                 -1 on error: errno =
第一个参数是共享内存的标识符。
第二个参数 shmaddr 指定了共享内存映射的地址。因为这样必须要预先分配内存,十分不便,所以我们在使用时常常将这

个参数置零,这样系统会自动为映射分配一块未使用的内存。如果指定了地址,可以给第三个参数 shmflg 指定SHM_RND

标志来强迫将内存大小设定为页面的尺寸。
如果指定了 SHM_RDONLY参数,共享内存将被映射成只读。
映射成功后,函数返回指向映射内存的指针。
下面的这段代码演示了 shmat()函数的使用:
char *attach_segment( int shmid )
{
         return(shmat(shmid, 0, 0));
}
得到了映射内存的指针之后,我们就可以像读写普通内存一样对共享内存进行读写了。

3、shmctl()函数
和前两个 IPC 对象一样,共享内存也有一个直接对其进行操作的函数,就是 shmctl()函数。
系统调用: shmctl()
函数声明:int shmctl(int shmqid, int cmd, struct shmid_ds *buf);
    返回值:0 on success
-1 on error: errno =

这个函数和 msgget()函数十分相似,用法也相同。它支持的操作有:
IPC_STAT   获得共享内存的信息。
IPC_SET   设定共享内存的信息。
IPC_RMID   删除共享内存。
需要说明的是,当执行 IPC_RMID 操作时,系统并不是立即将其删除,而只是将其标为待删,然后等待与其连接的进程断开连接。只有当所有的连接都断开以后系统才执行真正的删除操作。当然,如果执行 IPC_RMID 的时候没有任何的连接,删除将是立即的。

4、shmdt()函数
当一个进程不再需要某个共享内存的映射时,就应该使用 shmdt()函数断开映射。
系统调用: shmdt()
函数声明: int shmdt ( char *shmaddr );
    返回值: -1 on error: errno = EINVAL (Invalid attach address passed)
shmdt()函数唯一的参数是共享内存映射的指针。

共享内存应用举例——shmtool,交互式的共享内存使用工具
shmtool.c

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define SEGSIZE 100
writeshm(int shmid, char *segptr, char *text)
{
	strcpy(segptr, text);
	printf("Done..\n");
}
	
readshm(int shmid, char *segptr)
{
	printf("segptr: %s\n", segptr);
}
	
removeshm(int shmid)
{
	shmctl(shmid, IPC_RMID, 0);
	printf("Shared memory segment marked for deletion\n");
}

changemode(int shmid, char *mode)
{
	struct shmid_ds myshmds;

	/*Get current values for internal data structure */
	shmctl(shmid, IPC_STAT, &myshmds);
		
	/* Display old permissions */
	printf("Old permissions were:%o\n", myshmds.shm_perm.mode);

	/*Convert and load the mode */
	sscanf(mode, "%o", &myshmds.shm_perm.mode);
		
	/* Update the mode */
	shmctl(shmid, IPC_SET, &myshmds);

	printf("New permissions are: %o", myshmds.shm_perm.mode);

}
usage()
{
        	fprintf(stderr, "shmtool - A utility for tinkering with shared memory\n");
         	fprintf(stderr, "\nUSAGE:  shmtool (w)rite <text>\n");
        	fprintf(stderr, "                (r)ead\n");
         	fprintf(stderr, "                (d)elete\n");
         	fprintf(stderr, "                (m)ode change <octal mode>\n");
         	exit(1);
}
main(int argc, char *argv[])
{
	key_t key;
	int     shmid,cntr;
	char  *segptr;
	if(argc==1) usage();
	
	/*Create unique key via call to ftok() */
	key =ftok(".", 'S');

	/*Open the shared memory segment -create if necessary */
	if((shmid =shmget(key, SEGSIZE, IPC_CREAT|IPC_EXCL|0666))==-1)
	{
		printf("Shared memory segment exists - opening as client\n");
		/* Segment probably already exists - try as client */
		if((shmid = shmget(key, SEGSIZE, 0))==-1)
		{
			perror("shmget");
			exit(1);
		}


	}
	else{
		printf("Creating new shared memory segment\n");

	}
	
	/* Attach (map) the shared memory segment into the current process */
	if((segptr= shmat(shmid,0,0))==-1)
	{
		perror("shmat");
		exit(1);

	}
	
	switch(tolower(argv[1][0]))
	{
		case 'w': 
		writeshm(shmid, segptr, argv[2]);
                           	break;
		case 'r': 
		readshm(shmid, segptr);
                           	break;
                 	case 'd': 
		removeshm(shmid);
                          	break;
               		case 'm': 
		changemode(shmid, argv[2]);
                          	break;
                 	default: usage();

	}
	
}

/home/l/g/tomotoboy/ipc/shm >shmtool r
Shared memory segment exists - opening as client
segptr: test
/home/l/g/tomotoboy/ipc/shm >shmtool w "hello:this is a test"
Shared memory segment exists - opening as client
Done..
/home/l/g/tomotoboy/ipc/shm >shmtool r
Shared memory segment exists - opening as client
segptr: hello:this is a test
/home/l/g/tomotoboy/ipc/shm >shmtool d
Shared memory segment exists - opening as client
Shared memory segment marked for deletion
/home/l/g/tomotoboy/ipc/shm >shmtool r
Creating new shared memory segment
segptr:


分享到:
评论

相关推荐

    linux系统进程间通信——共享内存(System V版本)

    之前用过Prosix版本的共享内存和信号量,一直没有实践System V版本的,主要是因为其信号量集的概念操作有些复杂,今天试着写一个SV版本的共享内存进程间通信,使用信号量同步。程序提供了几个简单的用于操作SV版本...

    QT 进程间通信——共享内存-附件资源

    QT 进程间通信——共享内存-附件资源

    详解Linux进程间通信——使用共享内存

    共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式。这篇文章主要介绍了详解Linux进程间通信——使用共享内存,有兴趣的可以了解一下。

    进程间通信——匿名管道

    进程间通信(IPC,Inter-Process Communication)是操作系统中一种重要的机制,允许不同的进程之间交换数据,协同工作。在各种IPC方法中,匿名管道是一种简单且古老的通信方式,尤其适用于父子进程之间的通信。本篇...

    嵌入式操作系统实验报告

    河北工业大学《嵌入式操作系统》实验报告 实验一 Linux下C编程 实验二 搭建NFS服务器 实验三 守护进程 实验四 进程间通信——有名管道 实验五 进程间通信——...实验六 进程间通信——共享内存 综合实验——课程考核

    进程间通信之套接字( socket )——完整代码

    进程间通信之套接字( socket ) 网络间通信 七种进程间通信方式: 一.无名管道( pipe ) 二.有名管道( fifo ) 三.共享内存 ( shared memory ) 四.信号 ( sinal ) 五.消息队列 ( message queue ) 六.信号量 ( ...

    实验三、进程通信(一)——管道及共享内存.pdf

    整体来看,本文深入探讨了管道和共享内存这两种Linux进程通信机制的实现原理、方法和使用示例,旨在帮助读者理解和掌握这两种技术在进程间通信中的应用。通过实际的代码实例,我们可以看到如何在Linux环境下使用这些...

    操作系统的进程通信:共享内存、管道和消息队列的应用实现与解析

    内容概要:本文档详细介绍了MUC操作系统中三种不同的进程通信方式——共享内存、管道通信和消息队列的具体实现步骤与实验细节。每个部分不仅涵盖了相关概念和技术原理的简要介绍,还提供了一段或多段实际可操作性的...

    进程间通信之消息队列 ( message queue )——完整代码

    进程间通信之消息队列 ( message queue ) 消息队列是消息的链表,具有特定的格式,并由消息队列标识符标识. 七种进程间通信方式: 一.无名管道( pipe ) 二.有名管道( fifo ) 三.共享内存 ( shared memory ) 四....

    Linux 多进程及其通信

    "Linux进程间通信——使用共享内存.docx"将详细讲解如何创建、映射和操作共享内存,以及如何配合信号量确保数据一致性。 除了上述文档,链接文件如"CSDN博客中的相关文章"将提供额外的信息,这些博客可能包含作者...

    操作系统原理实验-进程间通信

    操作系统原理实验——进程间通信是计算机科学中一个关键的话题,特别是在多任务环境下,理解并实践进程间的通信机制至关重要。在本实验中,我们主要关注的是通过内存共享来实现进程间的实际通信,区别于单进程中的伪...

    高级进程间通信问题——快速排序问题1

    【高级进程间通信问题——快速排序问题1】的实验是一个基于操作系统原理的编程挑战,旨在实现一个多线程或多进程的快速排序算法。这个实验在Ubuntu 18.04.5 LTS环境下进行,采用C/C++编程语言,并且允许使用C++11的...

    进程通信(共享内存)

    在本场景中,我们关注的是"共享内存"这一通信机制,尤其在VB.NET环境中如何实现。共享内存允许多个进程访问同一块内存区域,从而高效地共享数据。 共享内存的优点在于它的高速性和直接性:因为数据直接存储在内存中...

    MFC教程lesson 17-进程间通信.rar

    4. **共享内存**:`CMemFile`和`CSharedFile`类可以帮助创建和访问共享内存,这是进程间通信的一种高效方式。 5. **命名管道**:MFC的`CNamedPipe`类使得通过管道进行进程间通信变得简单,这种通信方式适合大量数据...

    进行通信,共享内存方式

    在给定的标题“进行通信,共享内存方式”中,我们聚焦于一种高效的IPC机制——共享内存。共享内存允许多个进程访问同一块内存区域,从而实现数据的快速传递和同步。 共享内存的优点在于它提供了直接的数据访问,...

    实验一-进程通信——管道和信号实验报告.doc

    - **进程间通信(IPC)**:进程之间传递数据的方式,包括管道、信号量、共享内存等。 - **Unix系统编程基础**:熟悉C语言编程、shell命令行操作等。 #### 实验方法 本实验采用Unix系统提供的API进行编程,实现进程...

    Linux 下进程间通信实例

    Linux 下进程间通信实例之一——共享内存 使用了信号量用于进程间的同步

    Linux进程间通信(一)——Sam用图概述

    总结,Linux进程间通信是多任务环境下实现进程协作的关键,通过管道、信号量、消息队列、共享内存和套接字等多种手段,开发者可以构建出复杂而灵活的系统。结合Sam的图解学习,可以更好地理解和应用这些技术。

Global site tag (gtag.js) - Google Analytics