现在的位置: 首页 > 综合 > 正文

进程控制理论<三>—-共享内存

2014年09月05日 ⁄ 综合 ⁄ 共 2592字 ⁄ 字号 评论关闭

该文章参考于http://blog.csdn.net/yx_l128125/article/details/7688309,中间增加自己理解内容,在此先感谢这位大哥。

一.共享内存:

共享内存:是被多个进程共享的一部分物理内存。优点:

1、共享内存是进程间共享数据的一种最快的方式;

 
2、
一个进程向共享内存区域写入了数据,共享这个内存区域的所有进程就可以立即看到其中的内容。

         示意图如下:

              


二.共享内存的实现:

共享内存的实现分为两个步骤

(1)
创建共享内存(如上面示意图步骤1),使用shmget函数,返回共享内存标识符shmid。

(2)
映射共享内存(如上面示意图步骤2),将这段创建的共享映射到具体的进程空间去,使用shmat函数。

注:脱离和释放共享内存:当进程结束使用共享内存时,使用shmdt使共享内存脱离进程;当不需要共享内存时,使用shmctl(sid,IPC_RMID,0)删除它。

A.创建(分配)共享内存 

函数原型:int shmget(key_t 
key , int size ,int shmflg)

        参数:1、key:标识共享内存的键值:
/   IPC_PRIVATE.key的取值为IPC_PRIVATE,则函数shmget()将创建一块新的
                                       共享内存;如果
key的取值为0,而参数shmflg中又设置IPC_PRIVATE这个标志,则同样会创建一块新的共享内存。

                     2、size: 创建的共享内存的长度

                     3、shmflg:操作类型,也可用于设置共享内存的访问权限。例如:IPC_CREAT:如果共享内存不存在,则创建一                                              个共享内存,否则打开操作。

返回值:如果成功,返回共享内存标识符;如果失败,返回-1,errno存储错误原因

B、映射

         函数原型:int 
shmat(int shmid ,char *shmaddr ,int flag)     
shmat:连接共享内存)

         参数:

                  1、shmid :shmget函数返回的个共享内存标识符;

                  2、shmaddr :映射到进程地址空间的起始地址。一般为0;(表示有系统帮你找一个合适地址做映射)

                  3、 flag :本进程对该内存的操作模式。(通常为0

         返回值:如果成功,则返回共享内存映射到的进程的地址;如果失败,则返回-1

 C、脱离和释放共享内存

          当一个进程不再需要共享内存时,需要把它从进程地址空间中脱离。

         1、 脱离共享内存:

          函数原型:Int   shmdt (char *shmaddr)

          参数:shmaddr:指向共享内存映射到进程地址空间的起始地址的指针,即shmat()函数中shmaddr参数

          返回值:成功返回0,失败返回-1

          2、释放共享内存

           函数原型: int shmctl(int shmid ,int cmd,struct shmid_ds  *buf)

           参数:

                        1、shmid:共享内存ID

                        2、cmd 控制命令

                        3、buf:结构体指针 

          返回值:成功返回0,失败返回-1

源码:

/**********************************************************
**实验要求:   创建子进程,通过父子进程共享内存进行通讯。
**功能描述:   程序创建共享内存块和子进程。父进程向共享内存中写入数据,
**             子进程从共享内存中读取数据。 
**日    期:   2013年12月14日 
**作    者:   hailin 
**********************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define PERM S_IRUSR|S_IWUSR

/* 共享内存 */
int main(int argc,char **argv) 
{ 

	int shmid; 
	char *p_addr,*c_addr; 
	if(argc!=2) 
	{ 
		fprintf(stderr,"Usage:%s\n\a",argv[0]); 
		exit(1); 
	}
	/* 创建共享内存,内存size:1024byte,属性PERM:可读、可写 */ 
	if((shmid=shmget(IPC_PRIVATE,1024,PERM))==-1) 
	{ 	
		fprintf(stderr,"Create Share Memory Error:%s\n\a",strerror(errno)); 
		exit(1); 
	} 
	/* 创建子进程 */
	if(fork()) // 父进程写
	{ 
	/*把创建好的内存映射到父进程当中来,shmid:父进程的编号,第二个参数为0,即让系统自动帮找一个地址
	  shmat()返回值:如果成功,则返回共享内存映射到的进程的地址;如果失败,则返回-1;*/
		p_addr=shmat(shmid,0,0); 
	
		memset(p_addr,'\0',1024); /*让内存区全部为结束符*/
		strncpy(p_addr,argv[1],1024);
		wait(NULL); // 释放资源,不关心终止状态(等待子进程退出)
		exit(0); 
	} 
	else       // 子进程读
	{ 
		sleep(1); // 暂停1秒          
		c_addr=shmat(shmid,0,0); 
		printf("Client get %s\n",c_addr); 
		exit(0); 
	} 
}

运行结果:

终端输入:   ./shmem   1234567890
终端输出:   Client get 1234567890

小结:

1、如何保证两个进程与共享内存能成功映射?

通过shmid共享内存标识符,如果有两个进程想使用共享内存,则shmat(shimid,对应进程映射地址,操作模式)中shmid一致就ok了。

【上篇】
【下篇】

抱歉!评论已关闭.