Unix C编程:共享内存示例 测试代码
库函数说明参考来自博友,代码示例属个人原创
一、共享内存函数由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,却无足够的权限执行 |
二、代码如下
分为两个程序,一个程序获取共享内存,写入数据;另一个程序获取共享内存,读出数据;
当按下ctrl+c键结束程序,由shmset从系统中释放掉共享内存。
shmset.c
/*************************************************************************> File Name: shmset.c> Author: TANG> Mail: tjcmail@126.com > Created Time: 2018年04月02日 星期一 16时29分10秒************************************************************************/#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>/*共享内存结构*/
typedef struct{char name[12];char age;
}msg_t;/*共享内存地址*/
typedef struct{int shmid;void *addr;
}addr_t;/*变量声明*/
int RUNING = 1;/* 功能:自定义信号处理函数* 参数:* 返回值:无* */
void handler(int snum)
{RUNING = 0;
}/* 功能:初始化共享内存* 参数:无* 返回值:* */
addr_t *init_memory(addr_t *m_addr)
{key_t key = 0;int shmid = 0;void *addr = NULL;int flag = IPC_CREAT|0664;/*获取键值*/if(-1 == (key=ftok(".",64))){perror("ftok");return NULL;}/*申请一块共享内存*/if(-1 == (shmid=shmget(key,sizeof(msg_t),flag))){perror("shmget");return NULL;}/*建立映射关系*/if(NULL == (addr=shmat(shmid,NULL,0))){perror("shmat");return NULL;}m_addr->shmid = shmid;m_addr->addr = addr;return m_addr;
}
/* 功能:释放共享内存* 参数:共享内存编号,地址* 返回值:无* */
void del_memory(addr_t *m_addr){printf("开始注销共享内存!\n");/*解除共享内存与当前进程的映射关系*/if(-1 == (shmdt(m_addr->addr))){perror("shmdl");return;}/*删除共享内存*/int ret = 0;if(-1 == (ret = shmctl(m_addr->shmid, IPC_RMID, NULL))) //IPC_RMID为删除内存段{perror("shmctl");return;}
}
/* 函数名:main* 参数:无* 返回值:正常返回0 异常返回-1* */
int main(void){msg_t *message;//共享内存存储的内容addr_t *m_addr;//共享内存的地址char age = 0;/*信号处理函数*/signal(SIGINT,handler);/*初始化共享内存*/m_addr = init_memory(m_addr);/*获取共享内存用户空间地址*/message = m_addr->addr;/*循环设置共享内存内容*/while(RUNING){strcpy(message->name,"TANG");message->age = age;age++;sleep(2);}/*注销共享内存*/del_memory(m_addr);return 0;
}
shmget.c------------------------------------------------------------------------------------------------------------------------
/************************************************************************* > File Name: shmget.c> Author: TANG> Mail: tjcmail@126.com > Created Time: 2018年04月02日 星期一 16时29分10秒************************************************************************/#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <signal.h>
#include <unistd.h>/*共享内存结构*/
typedef struct{char name[12];char age;
}msg_t;
/*共享内存地址*/
typedef struct{int shmid;void *addr;
}addr_t;/*变量声明*/
int RUNING = 1;/* 功能:自定义信号处理函数* 参数:* 返回值:无* */
void handler(int snum){RUNING = 0;
}/* 功能:初始化共享内存* 参数:无* 返回值:* */
addr_t *init_memory(addr_t *m_addr)
{key_t key = 0;int shmid = 0;void *addr = NULL;int flag = IPC_CREAT|0664;/*获取键值*/if(-1 == (key=ftok(".",64))){perror("ftok");return NULL;}/*申请一块共享内存*/if(-1 == (shmid=shmget(key,sizeof(msg_t),flag))){perror("shmget");return NULL;}/*建立映射关系*/if(NULL == (addr=shmat(shmid,NULL,0))){perror("shmat");return NULL; }m_addr->shmid = shmid;m_addr->addr = addr;return m_addr;
}
/* 功能:释放共享内存* 参数:共享内存编号,地址* 返回值:无* */
void del_memory(addr_t *m_addr){printf("开始注销共享内存!\n");/*解除共享内存与当前进程的映射关系*/if(-1 == (shmdt(m_addr->addr))){perror("shmdl");return;}
}
/* 函数名:main* 参数:无* 返回值:正常返回0 异常返回-1* */
int main(void){msg_t *message;//共享内存存储的内容addr_t *m_addr;//共享内存的地址int age = 0;/*信号处理函数*/signal(SIGINT,handler);/*初始化共享内存*/m_addr = init_memory(m_addr);/*获取共享内存用户空间地址*/message = m_addr->addr;/*循环获取共享内存内容*/while(RUNING){ if(age != message->age){printf("Read message success!The name is %s,age is %d\n",message->name,message->age);age = message->age;}}del_memory(m_addr);return 0;
}
Unix C编程:共享内存示例 测试代码相关推荐
- 提高C++性能的编程技术笔记:多线程内存池+测试代码
为了使多个线程并发地分配和释放内存,必须在分配器方法中添加互斥锁. 全局内存管理器(通过new()和delete()实现)是通用的,因此它的开销也非常大. 因为单线程内存管理器要比多线程内存管理器快的 ...
- Multi-thread--提高C++性能的编程技术笔记:多线程内存池+测试代码
为了使多个线程并发地分配和释放内存,必须在分配器方法中添加互斥锁. 全局内存管理器(通过new()和delete()实现)是通用的,因此它的开销也非常大. 因为单线程内存管理器要比多线程内存管理器快的 ...
- 【Python】python初学者应该知道与其他语言差异化的高效编程技巧(附测试代码+详细注释)
目录 1. 交换变量 2. 集合去重 3. 列表推导.集合推导和字典推导 4. 统计字符串中各个字符出现的次数 5.优雅地打印JSON数据 6.行内的if语句 6. 符合正常逻辑的数值比较 7. 田忌 ...
- 提高C++性能的编程技术笔记:单线程内存池+测试代码
频繁地分配和回收内存会严重地降低程序的性能.性能降低的原因在于默认的内存管理是通用的.应用程序可能会以某种特定的方式使用内存,并且为不需要的功能付出性能上的代价.通过开发专用的内存管理器可以解决这个问 ...
- Multi-thread提高C++性能的编程技术笔记:单线程内存池+测试代码
频繁地分配和回收内存会严重地降低程序的性能.性能降低的原因在于默认的内存管理是通用的.应用程序可能会以某种特定的方式使用内存,并且为不需要的功能付出性能上的代价.通过开发专用的内存管理器可以解决这个问 ...
- 进程间通信:共享内存概念及代码
前言 接下讨论的IPC机制,它们最初由System V版本的Unix引入.由于这些机制都出现在同一个版本中并且有着相似的编程接口,所以它们被称为System V IPC机制.接下来的内容包括: 信号量 ...
- linux共享内存示例,linux 进程间共享内存示例
写入端: #include #include #include #include #include using namespace std; struct MappingDataType { int ...
- Linux系统编程 —共享内存之mmap
共享内存概念 共享内存是通信效率最高的IPC方式,因为进程可以直接读写内存,而无需进行数据的拷备.但是它没有自带同步机制,需要配合信号量等方式来进行同步. 共享内存被创建以后,同一块物理内存被映射到了 ...
- C++调用Lua编程环境搭建及测试代码示例
测试环境是VS2005+LuaForWindows_v5.1.4-45.exe+WIN7 1.安装lua开发环境LuaForWindows_v5.1.4-45.exe 2.启动VS2005,选择C++ ...
- lmbench内存延迟测试代码分析
lmbench有很多测试集, lat_mem_rd是用来测试内存延迟的 使用方法 ./bin/x86_64-linux-gnu/lat_mem_rd 1 16 ./bin/x86_64-linux-g ...
最新文章
- C# SortedDictionary以及SortedList的浅谈
- Elasticsearch2.x Cluster Health
- POI的入门:创建单元格设置数据
- 转载.Android HAL实现的三种方式(1) - 基于JNI的简单HAL设计
- OpenFire源码学习之十九:在openfire中使用redis插件(上)
- python元组和集合
- MyBatis:模糊查询的4种实现方式
- [5.数据类型] 零基础学python,简单粗暴
- qt 判断路径非英文符号与非英文字符_Qt中,软件多语言国际化翻译的方法与步骤...
- 汽车出租管理系统javaee实训_温州专业电动汽车充电设备实训台厂家诚信互利-嘉育仪器...
- Httpd总结 :HTTPD的基本概念
- 基于python+Django+MYSQL实现的图书管理系统
- 什么软件可以清除流氓软件
- [OHOS ERROR] FileNotFoundError: [Errno 2] No such file or directory: ‘python‘
- 中英文切换时英文的样式乱了怎么处理
- Bert:Pre-training of Deep Bidirectional Transformers forLanguage Understanding
- PDF太大如何压缩变小?
- STM32使能/屏蔽外部中断
- NB-IoT网络部署
- BSD是什么,车辆为什么要装BSD?