栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

多进程编程(四):共享内存

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

多进程编程(四):共享内存

定义:

共享内存(Shared Memory)就是允许两个或多个进程访问同一个内存空间,是在多进程通信的最高效的方式。
操作系统将不同进程之间共享内存安排为同一段物理内存,进程可以将共享内存连接到它们自己的地址空间中,如果某个进程修改了共享内存中的数据,其它的进程读到的数据也将会改变。由于共享内存会成为进程用户空间的一部分,所有这种通信方式不需要内核介入。
共享内存并未提供锁机制,也就是说,在某一个进程对共享内存的进行读写的时候,不会阻止其它的进程对它的读写,可能会出现数据的错乱。

函数:

1、必备头文件

#include 
#include 

2、shmget() 获取或创建共享内存

// 获取或者创建共享内存
int shmget(key_t key, size_t size, int shmflg);
- key是共享内存的键值,是一个整数,是共享内存在系统中的编号,不同共享内存的编号不同。一般使用十六进制。
- size表示待创建共享内存的大小,以字节为单位
- shmflg表示共享内存的访问权限,与文件的权限一样,
	0666 | IPC_CREAT 表示全部用户对它可读写
- 返回值:返回共享内存标识

3、shmat() 把共享内存连接到当前进程的地址空间

void *shmat(int shm_id, const void *shm_addr, int shmflg);
- shm_id表示由 shmget函数返回的 共享内存的标识号
- shm_addr指定共享内存连接到当前进程中的地址位置,通常为 NULL,表示让系统来选择共享内存的地址。
- shm_flg是一组标志位,通常为0
- 返回值:
	调用成功:返回一个指向共享内存第一个字节的指针
	调用失败:返回 -1

4、shmdt() 将共享内存从当前进程中分离,相当于 shmat()函数的反操作

int shmdt(const void *shmaddr);
- shmaddr是 shmat函数 返回的地址
- 返回值:
	调用成功:返回 0
	调用失败:返回 -1

5、shmctl() 删除共享内存

int shmctl(int shm_id, int command, struct shmid_ds *buf);
- shm_id是共享内存的标识号
- command 填写 IPC_RMID
- buf 填写 0
- 返回值:
	调用成功:返回 0
	调用失败:返回 -1
使用步骤
  • 调用 shmget() 函数创建一个新共享内存段或取得一个现有的共享内存段的标识号。返回后续可调用的需要用到的共享内存标识符。
  • 在进程中使用 shmat() 函数附上共享内存段,即让该共享内存段成为调用进程的虚拟内存中的一部分(进程绑定共享内存段)
  • 使用 shmat() 返回的内存地址指针,就可以在程序中对该共享内存段进行操作(写操作/读操作)。
  • 调用 shmdt() 函数,让进程和共享内存段分离,进程无法再操作共享内存了。(只是分离,共享内存依然存在)
  • 调用 shmctl() 函数,删除共享内存段,只有当与该共享内存段绑定好的进程都分离后,才会销毁,只有一个进程需要执行这一步。
举例
// write_shm.c
#include 
#include 
#include 
#include 
#include  

int main()
{
	int shmid; // 共享内存标识符
 
  	// 创建共享内存,键值为0x5005,共1024字节。
  	if ( (shmid = shmget((key_t)0x5005, 1024, 0666 | IPC_CREAT)) == -1)
  	{ 
		printf("shmat(0x5005) failedn"); 
		return -1; 
	}

  	char *ptext = NULL;   // 用于指向共享内存的指针
 
  	// 将共享内存连接到当前进程的地址空间,由ptext指针指向它
  	ptext = (char *)shmat(shmid, NULL, 0);
    
  	// 操作本程序的ptext指针,就是操作共享内存
    char *str = "Hello world!";
  	memcpy(ptext, str, strlen(str));
    
  	// 把共享内存从当前进程中分离
  	shmdt(ptext);

    return 0;
}
// read_shm.c

int main()
{
	int shmid; // 共享内存标识符
 
  	// 创建共享内存,键值为0x5005,共1024字节。
  	if ( (shmid = shmget((key_t)0x5005, 1024, 0666 | IPC_CREAT)) == -1)
  	{ 
		printf("shmat(0x5005) failedn"); 
		return -1; 
	}

  	char *ptext = NULL;   // 用于指向共享内存的指针
 
  	// 将共享内存连接到当前进程的地址空间,由ptext指针指向它
  	ptext = (char *)shmat(shmid, NULL, 0);
 
  	// 操作本程序的ptext指针,就是操作共享内存
  	printf("%sn", ptext);
 
  	// 把共享内存从当前进程中分离
  	shmdt(ptext);
   
  	// 删除共享内存
  	if (shmctl(shmid, IPC_RMID, 0) == -1)
  	{ 
		printf("shmctl(0x5005) failedn"); 
		return -1; 
	}
}

read_shm.c的输出结果:

Hello world!

可以看出,write_shm.c 申请共享内存,并写入数据,read_shm获取共享内存标识号,并绑定进程,读取该共享内存中的数据。

查看共享内存
ipcs -m # 查看现有的所有共享内存段

ipcrm -m shmid # 根据共享内存段的标识号,删除共享内存
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/993312.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号