Linux进程间通信:共享内存函数(shmget、shmat、shmdt、shmctl)及其范例
共享内存函数由shmget、shmat、shmdt、shmctl四个函数组成。下面的表格列出了这四个函数的函数原型及其具体说明。
1. shmget函数原型
shmget(得到一个共享内存标识符或创建一个共享内存对象) |
||
所需头文件 |
#include <sys/ipc.h> #include <sys/shm.h> |
|
函数说明 |
得到一个共享内存标识符或创建一个共享内存对象并返回共享内存标识符 |
|
函数原型 |
int shmget(key_t key, size_t size, int shmflg) |
|
函数传入值 |
key |
0(IPC_PRIVATE):会建立新共享内存对象 |
大于0的32位整数:视参数shmflg来确定操作。通常要求此值来源于ftok返回的IPC键值 |
||
size |
大于0的整数:新建的共享内存大小,以字节为单位 |
|
0:只获取共享内存时指定为0 |
||
shmflg |
0:取共享内存标识符,若不存在则函数会报错 |
|
IPC_CREAT:当shmflg&IPC_CREAT为真时,如果内核中不存在键值与key相等的共享内存,则新建一个共享内存;如果存在这样的共享内存,返回此共享内存的标识符 |
||
IPC_CREAT|IPC_EXCL:如果内核中不存在键值与key相等的共享内存,则新建一个消息队列;如果存在这样的共享内存则报错 |
||
函数返回值 |
成功:返回共享内存的标识符 |
|
出错:-1,错误原因存于error中 |
||
附加说明 |
上述shmflg参数为模式标志参数,使用时需要与IPC对象存取权限(如0600)进行|运算来确定信号量集的存取权限 |
|
错误代码 |
EINVAL:参数size小于SHMMIN或大于SHMMAX EEXIST:预建立key所指的共享内存,但已经存在 EIDRM:参数key所指的共享内存已经删除 ENOSPC:超过了系统允许建立的共享内存的最大值(SHMALL) ENOENT:参数key所指的共享内存不存在,而参数shmflg未设IPC_CREAT位 EACCES:没有权限 ENOMEM:核心内存不足 |
在Linux环境中,对开始申请的共享内存空间进行了初始化,初始值为0x00。
如果用shmget创建了一个新的消息队列对象时,则shmid_ds结构成员变量的值设置如下:
Ÿ shm_lpid、shm_nattach、shm_atime、shm_dtime设置为0。
Ÿ msg_ctime设置为当前时间。
Ÿ shm_segsz设成创建共享内存的大小。
Ÿ shmflg的读写权限放在shm_perm.mode中。
Ÿ shm_perm结构的uid和cuid成员被设置成当前进程的有效用户ID,gid和cuid成员被设置成当前进程的有效组ID。
2. shmat函数原型
shmat(把共享内存区对象映射到调用进程的地址空间) |
||
所需头文件 |
#include <sys/types.h> #include <sys/shm.h> |
|
函数说明 |
连接共享内存标识符为shmid的共享内存,连接成功后把共享内存区对象映射到调用进程的地址空间,随后可像本地空间一样访问 |
|
函数原型 |
void *shmat(int shmid, const void *shmaddr, int shmflg) |
|
函数传入值 |
msqid |
共享内存标识符 |
shmaddr |
指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置 |
|
shmflg |
SHM_RDONLY:为只读模式,其他为读写模式 |
|
函数返回值 |
成功:附加好的共享内存地址 |
|
出错:-1,错误原因存于error中 |
||
附加说明 |
fork后子进程继承已连接的共享内存地址。exec后该子进程与已连接的共享内存地址自动脱离(detach)。进程结束后,已连接的共享内存地址会自动脱离(detach) |
|
错误代码 |
EACCES:无权限以指定方式连接共享内存 EINVAL:无效的参数shmid或shmaddr ENOMEM:核心内存不足 |
3. shmdt函数原型
shmat(断开共享内存连接) |
|
所需头文件 |
#include <sys/types.h> #include <sys/shm.h> |
函数说明 |
与shmat函数相反,是用来断开与共享内存附加点的地址,禁止本进程访问此片共享内存 |
函数原型 |
int shmdt(const void *shmaddr) |
函数传入值 |
shmaddr:连接的共享内存的起始地址 |
函数返回值 |
成功:0 |
出错:-1,错误原因存于error中 |
|
附加说明 |
本函数调用并不删除所指定的共享内存区,而只是将先前用shmat函数连接(attach)好的共享内存脱离(detach)目前的进程 |
错误代码 |
EINVAL:无效的参数shmaddr |
4. shmctl函数原型
shmctl(共享内存管理) |
||
所需头文件 |
#include <sys/types.h> #include <sys/shm.h> |
|
函数说明 |
完成对共享内存的控制 |
|
函数原型 |
int shmctl(int shmid, int cmd, struct shmid_ds *buf) |
|
函数传入值 |
msqid |
共享内存标识符 |
cmd |
IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中 |
|
IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内 |
||
IPC_RMID:删除这片共享内存 |
||
buf |
共享内存管理结构体。具体说明参见共享内存内核结构定义部分 |
|
函数返回值 |
成功:0 |
|
出错:-1,错误原因存于error中 |
||
错误代码 |
EACCESS:参数cmd为IPC_STAT,确无权限读取该共享内存 EFAULT:参数buf指向无效的内存地址 EIDRM:标识符为msqid的共享内存已被删除 EINVAL:无效的参数cmd或shmid EPERM:参数cmd为IPC_SET或IPC_RMID,却无足够的权限执行 |
共享内存应用范例
5. 父子进程通信范例
父子进程通信范例,shm.c源代码如下:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <error.h>
#define SIZE 1024
int main()
{
int shmid ;
char *shmaddr ;
struct shmid_ds buf ;
int flag = 0 ;
int pid ;
shmid = shmget(IPC_PRIVATE, SIZE, IPC_CREAT|0600 ) ;
if ( shmid < 0 )
{
perror("get shm ipc_id error") ;
return -1 ;
}
pid = fork() ;
if ( pid == 0 )
{
shmaddr = (char *)shmat( shmid, NULL, 0 ) ;
if ( (int)shmaddr == -1 )
{
perror("shmat addr error") ;
return -1 ;
}
strcpy( shmaddr, "Hi, I am child process!\n") ;
shmdt( shmaddr ) ;
return 0;
} else if ( pid > 0) {
sleep(3 ) ;
flag = shmctl( shmid, IPC_STAT, &buf) ;
if ( flag == -1 )
{
perror("shmctl shm error") ;
return -1 ;
}
printf("shm_segsz =%d bytes\n", buf.shm_segsz ) ;
printf("parent pid=%d, shm_cpid = %d \n", getpid(), buf.shm_cpid ) ;
printf("chlid pid=%d, shm_lpid = %d \n",pid , buf.shm_lpid ) ;
shmaddr = (char *) shmat(shmid, NULL, 0 ) ;
if ( (int)shmaddr == -1 )
{
perror("shmat addr error") ;
return -1 ;
}
printf("%s", shmaddr) ;
shmdt( shmaddr ) ;
shmctl(shmid, IPC_RMID, NULL) ;
}else{
perror("fork error") ;
shmctl(shmid, IPC_RMID, NULL) ;
}
return 0 ;
}
编译 gcc shm.c –o shm。
执行 ./shm,执行结果如下:
shm_segsz =1024 bytes
shm_cpid = 9503
shm_lpid = 9504
Hi, I am child process!
6. 多进程读写范例
多进程读写即一个进程写共享内存,一个或多个进程读共享内存。下面的例子实现的是一个进程写共享内存,一个进程读共享内存。
(1)下面程序实现了创建共享内存,并写入消息。
shmwrite.c源代码如下:
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
typedef struct{
char name[8];
int age;
} people;
int main(int argc, char** argv)
{
int shm_id,i;
key_t key;
char temp[8];
people *p_map;
char pathname[30] ;
strcpy(pathname,"/tmp") ;
key = ftok(pathname,0x03);
if(key==-1)
{
perror("ftok error");
return -1;
}
printf("key=%d\n",key) ;
shm_id=shmget(key,4096,IPC_CREAT|IPC_EXCL|0600);
if(shm_id==-1)
{
perror("shmget error");
return -1;
}
printf("shm_id=%d\n", shm_id) ;
p_map=(people*)shmat(shm_id,NULL,0);
memset(temp, 0x00, sizeof(temp)) ;
strcpy(temp,"test") ;
temp[4]='0';
for(i = 0;i<3;i++)
{
temp[4]+=1;
strncpy((p_map+i)->name,temp,5);
(p_map+i)->age=0+i;
}
shmdt(p_map) ;
return 0 ;
}
(2)下面程序实现从共享内存读消息。
shmread.c源代码如下:
#include <stdio.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
typedef struct{
char name[8];
int age;
} people;
int main(int argc, char** argv)
{
int shm_id,i;
key_t key;
people *p_map;
char pathname[30] ;
strcpy(pathname,"/tmp") ;
key = ftok(pathname,0x03);
if(key == -1)
{
perror("ftok error");
return -1;
}
printf("key=%d\n", key) ;
shm_id = shmget(key,0, 0);
if(shm_id == -1)
{
perror("shmget error");
return -1;
}
printf("shm_id=%d\n", shm_id) ;
p_map = (people*)shmat(shm_id,NULL,0);
for(i = 0;i<3;i++)
{
printf( "name:%s\n",(*(p_map+i)).name );
printf( "age %d\n",(*(p_map+i)).age );
}
if(shmdt(p_map) == -1)
{
perror("detach error");
return -1;
}
return 0 ;
}
(3)编译与执行
① 编译gcc shmwrite.c -o shmwrite。
② 执行./shmwrite,执行结果如下:
key=50453281
shm_id=688137
③ 编译gcc shmread.c -o shmread。
④ 执行./shmread,执行结果如下:
key=50453281
shm_id=688137
name:test1
age 0
name:test2
age 1
name:test3
age 2
⑤ 再执行./shmwrite,执行结果如下:
key=50453281
shmget error: File exists
⑥ 使用ipcrm -m 688137删除此共享内存。
摘录自《深入浅出Linux工具与编程》
版权声明
原文链接:https://blog.csdn.net/guoping16/article/details/6584058
Linux进程间通信:共享内存函数(shmget、shmat、shmdt、shmctl)及其范例相关推荐
- c语言中shmget相关函数,共享内存函数(shmget、shmat、shmdt、shmctl)及其范例 - guoping16的专栏 - 博客频道 - CSDN...
2014年4月2日共享内存函数(shmget.shmat.shmdt.shmctl)及其范例 - guoping16的专栏 - 博客频道 - http://doc.xuehai.net 登录 | 注册 ...
- 共享内存(shmget,shmat,shmdt,shmctl)
共享内存shmgetshmatshmdtshmctl shmget int shmget(key_t key, size_t size, int flag); key: 标识符的规则 size:共享存 ...
- 【Linux】Linux进程间通信——共享内存/消息队列/守护进程
文章目录 进程间通信--共享内存/守护进程 一, 共享内存 1. 共享内存概念 2. 共享内存使用 1. 共享内存使用步骤 2. 共享内存操作函数 3. 共享内存常用操作命令 4. 共享内存使用示例: ...
- c++ fork 进程时 共享内存_c/c++ Linux 进程间通信------共享内存
1. 什么是共享内存 共享内存(Shared Memory),指两个或多个进程共享一个给定的存储区.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是 ...
- Linux 3.进程间通信(shmget shmat shmdt shmctl 共享内存、signal signaction sigqueue 信号、semget semctl semop 信号量)
Linux 3.进程间通信(IPC) 共享内存 共享内存的接口指令 shmget 创建获取获取共享内存 shmat 映射:连接共享内存到当前进程的地址空间 shmdt 断开与共享内存的连接 shmct ...
- Linux --进程间通信--共享内存
一.共享内存 共享内存是最高效的通信方式,因为不需要一个进程先拷贝到内核,另一个进程在存内核中读取. 二. ipcs -m 查看共享内存 ipcrm -m 删除共享内存 三.主要函数 shmget 创 ...
- linux如何创建共享内存,linux实现共享内存同步的四种方法
https://blog.csdn.net/sunxiaopengsun/article/details/79869115 本文主要对实现共享内存同步的四种方法进行了介绍. 共享内存是一种最为高效的进 ...
- 【Linux】共享内存(shm)代码实现
文章目录 共享内存介绍 最快的IPC形式 共享内存示意图 共享内存数据结构 共享内存函数 shmget函数 shmfig shmat函数 说明: shmdt函数 shmctl函数 共享内存的原理 小结 ...
- IPC(进程间通信) | 共享内存
文章目录 共享内存 共享内存函数 shmget函数 shmat函数 shmdt函数 shmctl函数 示例1(未使用信号量同步版本) 示例2(使用信号量同步版本) 共享内存的特点 共享内存 共享内存区 ...
最新文章
- IE浏览器与非IE浏览器JS日期兼容性问题处理
- ConcurrentHashMap的源码分析-put方法第二阶段
- sqlserver 过滤html,sqlserver 过滤掉某些字段查询剩余字段的方法
- 注意力机制BAM和CBAM详细解析(附代码)
- STM32F103系统滴答计时器
- JAVA程序错误总结
- python爬虫什么意思-python爬虫什么意思
- BMFONT制作位图字体并在CocosCreator中使用
- 脑智前沿科普:脑深部电刺激治疗帕金森病的原理
- 《深度学习》之 VGG卷积神经网络 原理 详解
- Frsky X9D Plus遥控器和 Frisky R8 Pro接收机对频
- 数据结构初阶——二叉树
- Tongweb 7 集中管理工具
- Postman中tests的基本使用
- js案例一 :方块拖动效果
- java single threaded_[Java多线程设计模式]读书笔记 - 第一章 Single Threaded Execution
- SAP中状态参数文件最高状态和最低状态的理解
- electron 自动更新 热跟新
- 全球与中国磨料水射流切割机市场深度研究分析报告
- Springboot养老院管理系统
热门文章
- PB :图片显示+数据库保留图片路径
- 1.2 微型计算机的分类
- 自动化检测发现漏洞---AWVS
- java unchecked 警告_警告: [unchecked] 未经检查的转换
- 数据库优化 - SQL优化
- mysql version 乐观锁_mysql乐观锁总结和实践
- python SSL: CERTIFICATE_VERIFY_FAILED c1129
- JS实现细胞自动机小游戏
- java properties转map
- 三本深圳大学计算机考研,“三本生”拼考研 重启“高考模式”