共享内存函数(shmget、shmat、shmdt、shmctl)及其范例 - guoping16的专栏 - 博客频道 - CSDN
linux下c语言编程4-使用共享内存实现进程间通信

linux下C语言编程4-使用共享内存实现进程间通信共享内存的函数有以下几个:(1)int shmget(key_t key, int size, int shmflg),开辟或使用一块共享内存。
(2)void *shmat(int shmid, const void *shmaddr, int shmflg),将参数shmid所指向的共享内存与当前进程连接。
当使用某共享内存时,需要先使用shmat,达成连接。
(3)int shmdt(const void *shmaddr),将先前用shmat连接的共享内存与当前进程解除连接。
参数shmaddr为shmat返回的共享内存的地址。
在完成对共享内存的使用后,需要使用shmdt解除连接。
(4)int shmctl(int shmid, int cmd, struct shmid_ds *buf),控制内存的操作。
当cmd 为IPC_RMID时,删除shmid所指的共享内存。
这些函数的表头文件为<sys/ipc.h>和<sys/shm.h>,其详细参数请去网上搜索。
下面给出一个使用共享内存实现进程间通信的例子:进程A开辟一块新的共享内存,进程B 修改这个共享内存,进程C打印输出这个共享内存的内容,进程D删除这个共享内存。
进程BCD运行的命令格式为:命令共享内存ID,如./output 123432。
进程A代码如下:int main(){int shmid;shmid = shmget(IPC_PRIVATE, SIZE, IPC_CREAT | 0600);if (shmid < 0){perror("shmget error");exit(1);}printf("create shared memory OK. shmid=%d/n", shmid);return 0;}进程B代码如下:int main(int argc, char *argv[]){int shmid;char *shmaddr;if (argc != 2){perror("argc error/n");exit(1);}shmid = atoi(argv[1]);shmaddr = (char *)shmat(shmid, NULL, 0); if ((int )shmaddr == -1){perror("shmat error./n");exit(1);}strcpy(shmaddr, "hello, world!");shmdt(shmaddr);return 0;}进程C代码如下:int main(int argc, char *argv[]){int shmid;char *shmaddr;if (argc != 2){printf("argc error/n");exit(1);}shmid = atoi(argv[1]);shmaddr = (char *)shmat(shmid, NULL, 0); if ((int )shmaddr == -1){perror("shmat error./n");exit(1);}printf("%s/n", shmaddr);shmdt(shmaddr);return 0;}进程D代码如下:int main(int argc, char *argv[]){int shmid;if (argc != 2){perror("argc error/n");exit(1);}shmid = atoi(argv[1]);shmctl(shmid, IPC_RMID, NULL);return 0;}linux下C语言编程5-多线程编程Linux系统下的多线程遵循POSIX线程接口,称为pthread。
共享内存应用范例

共享内存应⽤范例1、⽗⼦范例⽗⼦进程通信范例,shm.c源代码如下:#include <stdio.h>#include <unistd.h>#include <string.h>#include <sys/ipc.h>#include <sys/shm.h>#include <error.h>#define SIZE 1024int 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。
08 共享内存

{
perror("shmget error");
exit(1) ;
}
pid = fork(); /* 创建子进程 */
if(pid<0) /* 如果进程创建失败,输出错误信息并退出 */
psm = shmat(shmid, NULL, 0); /* 将共享内存映射到进程的地址空间中 */
if(psm == -1) /* 如果映射失败,输出错误信息并退出 */
{
perror("shmat error\n");
exit(1);
}
else /* 共享内存映射成功 */
{
strcpy((char *)psm, argv[1]); /* 向共享内存中写入数据,这里传入为命令行参数 */
printf("Send message : %s\n", (char *)psm);
if(shmid < 0)
{
perror("shmget error"); /* 如果共享内存创建失败,输出错误信息并退出 */
exit(1) ;
}
else
{
printf("Done!\n");
}
return 0;
}
运行程序:./example15
psm = shmat(shmid, NULL, 0); /* 将共享内存映射到进程的地址空间中 */
if(psm == -1) /* 如果映射失败,输出错误信息并退出 */
共享内存函数(shmget、shmat、shmdt、shmctl)及其范例 - guoping16的专栏 - 博客频道 - CSDN

System V 进程间通讯(IPC、ftok (1) ) 进程的堆栈空间 字符串和内存操作函数 格式化I/O函数 C语言预处理 C语言结构体 (1) (1) (0) (0) (0)
推荐文章 * 阿里实习生招聘笔试题目 * Android 中Touch(触屏)事件 传递机制 * Android UI:看看Google官方自 定义带旋转动画的ImageView * List、Set和Map区别 * android SQLite数据库用法图 文详解(附源码) * 【C解析之七】文件进阶
shm_perm结构的uid和cuid成员被设置成当前进程的有效用户ID,gid和cuid成员被 设置成当前进程的有效组ID。 2. shmat函数原型 shmat(把共享内存区对象映射到调用进程的地址空间) 所需 #include <sys/types.h> 头文 #include <sys/shm.h> 件 函数 连接共享内存标识符为shmid的共享内存,连接成功后把共享内存区对象映射到调 说明 用进程的地址空间,随后可像本地空间一样访问 *shmat(int shmid, const void *shmaddr, int shmflg)
/guoping16/article/details/6584058
1/10
2014年4月2日
评论排行
共享内存函数(shmget、shmat、shmdt、shmctl)及其范例 - guoping16的专栏 - 博客频道 -
函数 成功:返回共享内存的标识符 返回 消息队列函数(msgget、msgctl (4) 、msgsnd、 msgrcv)及其范例 值 出错:-1,错误原因存于error中
最新评论 消息队列函数(msgget、msgctl、msgsnd、msgrcv)及其范例 daemon_msg: 很有帮助!谢谢 消息队列函数(msgget、msgctl、msgsnd、msgrcv)及其范例 mysee1989: 挺详细的。谢谢 进程的堆栈空间 wangpeng2011314: 那么 windows 下的原理一致吗 ??? 会话、进程组与僵死进程 guoping16: 1.当登录终端时,就 产生一个会话,也就产生了一个 可操作的界面。2.proc3 | proc4 | p... 会话、进程组与僵死进程 mmwren: 你好,有个问题请教 一下,当登录终端时,shell进程 为首进程,也是前台进程吗?在 执行命令 proc3... System V 进程间通讯(IPC、ftok) luguangxu68: 很不错啊! 谢谢 了 字符串和内存操作函数 asdk77: 总结的真好!收下了! 标准I/O文件编程 luguangxu68: 嗨,哥们,你很 棒!!!加油
Linux共享内存编程实例

printf( "shmat(
) failed/n" );
printf( "shared memory segment not found/n" ); return 0;
101. /*内存共享区段与旗语和消息队列不同,一个区段可以被锁定。 102. 103. 104. 105. 被锁定的区段不允许被交换出内存。这样做的优势在于,与其 把内存区段交换到文件系统,在某个应用程序调用时再交换回内存, 不如让它一直处于内存中,且对多个应用程序可见。从提升性能的角度 来看,很重要的。
166. 167. 168. 169. 170. } else if( !strncmp(argv[ 1 ],"use",3) ) { /*use the segment*/
171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. }
15. /* 16. 17. 18. 19. 20. 21. 22. 23. shmat( shmdt( */ ) ) shmctl( ) shmget( ) 创建一个新的共享内存区段 取得一个共享内存区段的描述符 取得一个共享内存区段的信息 为一个共享内存区段设置特定的信息 移除一个共享内存区段 挂接一个共享内存区段 于一个共享内存区段的分离
//must specify
共享内存使用

"shmget(%uz) failed", shm->size);
return NGX_ERROR;
}
ngx_log_debug1(NGX_LOG_DEBUG_CORE, shm->log, 0, "shmget id: %d", id);
②:如果参数key不是IPC_PRIVATE,也不是已经建立的IPC key, 那么系统会根据shmflg是否有IPC_CREAT位(shmflg | IPC_CREAT)
为真来决定IPC key为参数的共享内存。
③:如果参数包含了IPC_CREAT 和 IPC_EXECL位, 那么如果key标识的共享内存已经存在, 那么会报EEXIST的错误。
共享内存(Shared Memory)是最简单的进程间通信方式,它允许多个进程访问相同的内存,一个进程改变其中的数据后,其他的进程都可以看到数据的变化。
共享内存是进程间最快速的通信方式:
①进程共享同一块内存空间。
②访问共享内存和访问私有内存一样快。
③不需要系统调用和内核入口。
④不造成不必要的内存复制。
②:在经过fork()后, 子进程将继承已连接的共享内存地址,
③:在经过exec()函数后, 已连接的共享内存地址会自动脱离(detach)
④:进程结束后,已连接的共享内存会自动脱离
脱离:shmdt
函数原型:shmdt(const void *shmaddr);
①:shmdt()用来脱离先前shmat()过的共享内存。
if (shmdt(shm->addr) == -1) {
进程的共享存储区通信--带答案版

实验二进程管理2.4 进程的共享存储区通信1.实验目的(1) 通过编写共享存储区的通信程序,理解Linux共享存储区机制。
(2) 掌握进程共享存储区通信相关系统调用。
(3) 理解系统调用和用户命令的区别。
2.实验类型:验证型3.实验学时:24.实验原理和知识点(1) 实验原理:并发运行的进程之间,可以通过共享存储机制进行通信。
(2) 知识点:共享存储的创建、附接和断接5.实验环境(硬件环境、软件环境):(1)硬件环境:Intel Pentium III 以上CPU,128MB以上内存,2GB以上硬盘(2)软件环境:linux操作系统。
6. 预备知识(1) 共享存储区共享存储区机制直接通过共享虚拟存储空间进行通信。
通信时,进程首先提出申请,系统为之分配存储空间并返回共享区标示符。
这时,进程把它附加到自己的虚拟存储空间中。
通信的进程对共享区的访问要互斥地进行。
(2) shmget()系统调用:头文件 #include <sys/shm.h>函数原型 int shmget(key_t key, int size, int flag);功能:申请一个共享存储区。
成功返回共享内存标识符,失败则返回-1。
参数:key是共享存储区关键字。
size是存储区大小。
flag访问权限和控制标志。
(3) shmat()系统调用:头文件 #include <sys/shm.h>函数原型 int shmat(int id, char *addr, int flag);功能:将一个共享存储区附接到进程的虚地址空间。
成功返回起始地址,失败则返回-1。
数:id是共享存储区标识符。
addr是附接的虚地址。
flag访问权限和控制标志。
(4) shmdt()系统调用:头文件 #include <sys/shm.h>函数原型 int shmdt(char *addr);功能:一个共享存储区与指定进程的断开。
共享内存的原理

共享内存不同进程共享内存示意图共享内存指在多处理器的计算机系统中,可以被不同中央处理器(CPU)访问的大容量内存。
由于多个CPU需要快速访问存储器,这样就要对存储器进行缓存(Cache)。
任何一个缓存的数据被更新后,由于其他处理器也可能要存取,共享内存就需要立即更新,否则不同的处理器可能用到不同的数据。
共享内存(shared memory)是 Unix下的多进程之间的通信方法 ,这种方法通常用于一个程序的多进程间通信,实际上多个程序间也可以通过共享内存来传递信息。
目录共享内存的创建共享内存是存在于内核级别的一种资源,在shell中可以使用ipcs命令来查看当前系统IPC中的状态,在文件系统/proc目录下有对其描述的相应文件。
函数shmget可以创建或打开一块共享内存区。
函数原型如下:#include <sys/shm.h>int shmget( key_t key, size_t size, int flag );函数中参数key用来变换成一个标识符,而且每一个IPC对象与一个key相对应。
当新建一个共享内存段时,size参数为要请求的内存长度(以字节为单位)。
注意:内核是以页为单位分配内存,当size参数的值不是系统内存页长的整数倍时,系统会分配给进程最小的可以满足size长的页数,但是最后一页的剩余部分内存是不可用的。
当打开一个内存段时,参数size的值为0。
参数flag中的相应权限位初始化ipc_perm结构体中的mode域。
同时参数flag是函数行为参数,它指定一些当函数遇到阻塞或其他情况时应做出的反应。
shmid_ds结构初始化如表14-4所示。
初始化if (shm_id < 0 ) { /*创建共享内存*/perror( "shmget" ) ;exit ( 1 );}printf ( "successfully created segment : %d \n", shm_id ) ;system( "ipcs -m"); /*调用ipcs命令查看IPC*/exit( 0 );}(2)在shell中编译该程序如下:$gcc create_shm.c–o create_shm(3)在shell中运行该程序如下:$./ create_shmsuccessfully created segment : 2752516------ Shared Memory Segments --------key shmid owner perms bytes nattch status0x00000000 65536 root 600 393216 2 dest0x00000000 2654209 root 666 4096 00x0056a4d5 2686978 root 600 488 10x0056a4d6 2719747 root 600 131072 10x00000000 2752516 root 666 4096 0上述程序中使用shmget函数来创建一段共享内存,并在结束前调用了系统shell命令ipcs –m来查看当前系统IPC状态。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
IPC_CREAT :当shmflg&IPC_CREAT 为真时,如果内核中不存在键值与 信号的发送和捕捉函数(alarm (1719) 、kill、raise、pause、 sleep、 abort) key 相等的共享内存,则新建一个共享内存;如果存在这样的共享内存,返 进程的堆栈空间 (1247) 回此共享内存的标识符
/guoping16/article/details/6584058
1/10
2014年4月2日
评论排行
共享内存函数(shmget、shmat、shmdt、shmctl)及其范例 - guoping16的专栏 - 博客频道 -
函数 成功:返回共享内存的标识符 返回 消息队列函数(msgget、msgctl (4) 、msgsnd、 msgrcv)及其范例 值 出错:-1,错误原因存于error中
分类: Linux进程间通信 struct 目录(?) guoping16 null cmd gcc [+] linux 编程 2011-07-04 17:38 13141人阅读 评论(0) 收藏 举报
访问: 52118次 积分: 946分 排名: 第15089名 原创: 48篇 译文: 0篇 转载: 2篇 评论: 12条
最新评论 消息队列函数(msgget、msgctl、msgsnd、msgrcv)及其范例 daemon_msg: 很有帮助!谢谢 消息队列函数(msgget、msgctl、msgsnd、msgrcv)及其范例 mysee1989: 挺详细的。谢谢 进程的堆栈空间 wangpeng2011314: 那么 windows 下的原理一致吗 ??? 会话、进程组与僵死进程 guoping16: 1.当登录终端时,就 产生一个会话,也就产生了一个 可操作的界面。2.proc3 | proc4 | p... 会话、进程组与僵死进程 mmwren: 你好,有个问题请教 一下,当登录终端时,shell进程 为首进程,也是前台进程吗?在 执行命令 proc3... System V 进程间通讯(IPC、ftok) luguangxu68: 很不错啊! 谢谢 了 字符串和内存操作函数 asdk77: 总结的真好!收下了! 标准I/O文件编程 luguangxu68: 嗨,哥们,你很 棒!!!加油
ENOENT :参数key所指的共享内存不存在,而参数shmflg未设IPC_CREAT 位 EACCES:没有权限 ENOMEM:核心内存不足 在Linux环境中,对开始申请的共享内存空间进行了初始化,初始值为0x00。 如果用shmget创建了一个新的消息队列对象时,则shmid_ds结构成员变量的值设置如 下: s h m _ l p i d 、s h m _ n a t t a c h 、s h m _ a t i m e 、s h m _ d t i m e 设置为0。 msg_ctime设置为当前时间。 s h m _ s e g s z 设成创建共享内存的大小。 shmflg的读写权限放在shm_perm.mode中。
文章搜索
文章分类 Linux进程编程 (13) Linux进程间通信 (8) Linux网络编程 (6) C语言 (14) libxml编程 (7) 深入浅出Linux工具与编程 (2)
文章存档 2011年08月 (2) 2011年07月 (48)
Байду номын сангаас
阅读排行
0:只获取共享内存时指定为0 共享内存函数(shmget、shmat、shmdt、shmctl)及其范例 (13140) 消息队列函数(msgget、msgctl (4256) 、msgsnd、msgrcv)及其范例 shmflg 0:取共享内存标识符,若不存在则函数会报错 信号量函数(semget、semop (4178) 、semctl)及其范例
System V 进程间通讯(IPC、ftok (1) ) 进程的堆栈空间 字符串和内存操作函数 格式化I/O函数 C语言预处理 C语言结构体 (1) (1) (0) (0) (0)
推荐文章 * 阿里实习生招聘笔试题目 * Android 中Touch(触屏)事件 传递机制 * Android UI:看看Google官方自 定义带旋转动画的ImageView * List、Set和Map区别 * android SQLite数据库用法图 文详解(附源码) * 【C解析之七】文件进阶
消息队列函数(msgget、msgctl、msgsnd、msgrcv)及其范例 winjee: 挺详细的。不错 信号量函数(semget、semop、semctl)及其范例 函数 void 土官: /*若val==0时阻塞等待信号 量为0,调用进程进入睡眠状 原型 态,直到信号值为0;若设置 IPC_NOWA...
2014年4月2日
共享内存函数(shmget、shmat、shmdt、shmctl)及其范例 - guoping16的专栏 - 博客频道 -
返回 值 出错:-1,错误原因存于error中 附加 fork后子进程继承已连接的共享内存地址。exec后该子进程与已连接的共享内存地 说明 址自动脱离(detach)。进程结束后,已连接的共享内存地址会自动脱离(detach)
shm_perm结构的uid和cuid成员被设置成当前进程的有效用户ID,gid和cuid成员被 设置成当前进程的有效组ID。 2. shmat函数原型 shmat(把共享内存区对象映射到调用进程的地址空间) 所需 #include <sys/types.h> 头文 #include <sys/shm.h> 件 函数 连接共享内存标识符为shmid的共享内存,连接成功后把共享内存区对象映射到调 说明 用进程的地址空间,随后可像本地空间一样访问 *shmat(int shmid, const void *shmaddr, int shmflg)
错误 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 共享内存标识符 入值
共享内存函数由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的整数:新建的共享内存大小,以字节为单位
函数 msqid 共享内存标识符 传入 值 shmaddr 指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核 自己决定一个合适的地址位置 shmflg SHM_RDONLY:为只读模式,其他为读写模式
函数 成功:附加好的共享内存地址
/guoping16/article/details/6584058 2/10
/guoping16/article/details/6584058 3/10
2014年4月2日
共享内存函数(shmget、shmat、shmdt、shmctl)及其范例 - guoping16的专栏 - 博客频道 -
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 ;