共享内存函数(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状态。
共享内存使用方法
共享内存---shmget shmat shmdt 要使用共享内存,应该有如下步骤:1.开辟一块共享内存shmget()2.允许本进程使用共某块共享内存shmat()3.写入/读出4.禁止本进程使用这块共享内存shmdt()5.删除这块共享内存shmctl()或者命令行下ipcrmftok()。
它有两个参数,一个是字符串,一个是字符。
字符串一般用当前进程的程序名,字符一般用来标记这个标识符所标识的共享内存是这个进程所开辟的第几个共享内存。
ftok()会返回一个key_t型的值,也就是计算出来的标识符的值。
shmkey = ftok( "mcut" , 'a' ); // 计算标识符操作共享内存,我们用到了下面的函数#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>int shmget( key_t shmkey , int shmsiz , int flag );void *shmat( int shmid , char *shmaddr , int shmflag );int shmdt( char *shmaddr );shmget()是用来开辟/指向一块共享内存的函数。
参数定义如下:key_t shmkey 是这块共享内存的标识符。
如果是父子关系的进程间通信的话,这个标识符用IPC_PRIV A TE来代替。
但是刚才我们的两个进程没有任何关系,所以就用ftok()算出来一个标识符使用了。
int shmsiz 是这块内存的大小.int flag 是这块内存的模式(mode)以及权限标识。
模式可取如下值:新建:IPC_CREA T使用已开辟的内存:IPC_ALLOC如果标识符以存在,则返回错误值:IPC_EXCL然后将“模式” 和“权限标识”进行“或”运算,做为第三个参数。
共享内存的原理
共享内存不同进程共享内存示意图共享内存指在多处理器的计算机系统中,可以被不同中央处理器(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状态。
shm通信实例 -回复
shm通信实例-回复什么是shm通信?如何使用shm进行进程间通信?在计算机科学领域,进程间通信(IPC)是非常重要的概念。
它允许不同的进程在运行时相互传递数据和信息,以实现协作和共享资源。
共享内存(Shared Memory)是一种高效的进程间通信方式之一,shm通信就是利用共享内存进行进程间通信的一种方法。
共享内存是一块被操作系统映射到多个进程地址空间的内存区域。
这意味着多个进程可以将这块内存用作共享的工作区,彼此之间可以直接读写数据,而不需要复制或发送数据。
shm通信使得进程间的数据传输非常高效,适用于需要频繁交换大量数据的场景。
那么,如何使用shm进行进程间通信呢?接下来,我将一步一步地回答这个问题。
一、创建和连接共享内存步骤一是创建共享内存段,步骤二是将共享内存段连接到进程地址空间。
1. 创建共享内存段:调用shmget系统调用函数,指定共享内存端的键值、大小和权限。
这个调用将返回一个唯一的标识符(通常是一个非负整数),用于后续的进程间通信操作。
2. 连接共享内存段:使用shmat系统调用函数,将共享内存段连接到进程的地址空间。
这个调用将返回共享内存段在进程地址空间中的起始地址,可以将其分配给一个指针变量。
二、使用共享内存进行数据通信步骤三是使用共享内存进行进程间的数据通信。
1. 写入数据:在进程A中,将需要发送的数据写入共享内存中。
可以通过在指针变量上进行赋值操作来完成。
注意,为了避免并发问题,需要使用同步机制(如互斥锁)来保护共享内存的写操作。
2. 读取数据:在进程B中,读取共享内存中的数据。
同样地,需要使用同步机制来保护共享内存的读操作。
三、删除共享内存步骤四是在通信完成后删除共享内存段。
1. 分离共享内存:调用shmdt系统调用函数,将共享内存段从进程的地址空间中分离出来。
这个调用将取消进程与共享内存段的连接。
2. 删除共享内存段:如果所有的进程都分离了共享内存段,那么这个共享内存段将变得不再被使用。
Linux进程间通信(六):共享内存shmget()、shmat()、shmdt()、sh。。。
Linux进程间通信(六):共享内存shmget()、shmat()、shmdt()、sh。
下⾯将讲解进程间通信的另⼀种⽅式,使⽤共享内存。
⼀、什么是共享内存顾名思义,共享内存就是允许两个不相关的进程访问同⼀个逻辑内存。
共享内存是在两个正在运⾏的进程之间共享和传递数据的⼀种⾮常有效的⽅式。
不同进程之间共享的内存通常安排为同⼀段物理内存。
进程可以将同⼀段共享内存连接到它们⾃⼰的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由⽤C语⾔函数malloc()分配的内存⼀样。
⽽如果某个进程向共享内存写⼊数据,所做的改动将⽴即影响到可以访问同⼀段共享内存的任何其他进程。
特别提醒:共享内存并未提供同步机制,也就是说,在第⼀个进程结束对共享内存的写操作之前,并⽆⾃动机制可以阻⽌第⼆个进程开始对它进⾏读取。
所以我们通常需要⽤其他的机制来同步对共享内存的访问,例如前⾯说到的信号量。
有关信号量的更多内容,可以查阅另⼀篇⽂章:⼆、共享内存的使得与信号量⼀样,在Linux中也提供了⼀组函数接⼝⽤于使⽤共享内存,⽽且使⽤共享共存的接⼝还与信号量的⾮常相似,⽽且⽐使⽤信号量的接⼝来得简单。
它们声明在头⽂件sys/shm.h中。
1、shmget()函数该函数⽤来创建共享内存,它的原型为:int shmget(key_t key, size_t size, int shmflg);第⼀个参数,与信号量的semget函数⼀样,程序需要提供⼀个参数key(⾮0整数),它有效地为共享内存段命名,shmget()函数成功时返回⼀个与key相关的共享内存标识符(⾮负整数),⽤于后续的共享内存函数。
调⽤失败返回-1.不相关的进程可以通过该函数的返回值访问同⼀共享内存,它代表程序可能要使⽤的某个资源,程序对所有共享内存的访问都是间接的,程序先通过调⽤shmget()函数并提供⼀个键,再由系统⽣成⼀个相应的共享内存标识符(shmget()函数的返回值),只有shmget()函数才直接使⽤信号量键,所有其他的信号量函数使⽤由semget函数返回的信号量标识符。
共享内存的用法
共享内存的用法报告文档00125唐延军共享内存简介:应该包含的头文件#include <sys/ipc.h>#include <sys/shm.h>应该要用到的函数int shmget(key_t key,int size,int shmflg);void *shmat(int shmid,const void *shmaddr,int shmflg);int shmdt(const void *shmaddr);int shmctl(int shmid,int cmd,struct shmid_ds *buf);shmget是创建一块共享内存,size是共享内存的大小. shmflg 可以为IPC_CREAT或者IPC_EXCL。
如果使用IPC_CREA T要么返回一个新创建的共享内存的标识符,要么返回具有相同关键字值的共享内存的标识符。
Shmctl是对共享内存的控制.可以设置所有者,组对共享内存的存取权限。
也可以释放共享内存。
struct shmid_ds的定义如下struct shmid_ds {struct ipc_perm shm_perm; /* 存取权限*/int shm_segsz; /* 共享内存大小(byte) */time_t shm_atime; /* 最后使用时间 */time_t shm_dtime; /* 最后断开时间 */time_t shm_ctime; /* 最后修改时间 */unsigned short shm_cpid; /* pid of creator */unsigned short shm_lpid; /* pid of last operator */short shm_nattch; /* no. of current attaches */...};cmds 参数可以为:IPC_STAT, IPC_SET,IPC_RMID。
linux内存共享实现机制
linux内存共享实现机制Linux是一种开源的操作系统,其内存管理机制非常灵活和高效。
其中,内存共享是一种重要的机制,它允许多个进程共享同一块内存区域,从而提高系统的性能和资源利用率。
本文将介绍Linux内存共享的实现机制。
在Linux中,内存共享主要通过共享内存段来实现。
共享内存段是一块被多个进程共享的内存区域,进程可以通过映射共享内存段到自己的地址空间来访问其中的数据。
Linux提供了一系列的系统调用函数,如shmget、shmat、shmdt和shmctl,用于创建、连接、断开和控制共享内存段。
首先,进程需要调用shmget函数来创建一个共享内存段。
该函数接受三个参数,分别是共享内存的键值、大小和权限。
键值是一个唯一的标识符,用于标识共享内存段。
大小指定了共享内存段的大小,单位是字节。
权限用于控制对共享内存段的访问权限。
创建共享内存段后,进程可以调用shmat函数来连接到共享内存段。
该函数接受两个参数,分别是共享内存段的标识符和连接地址。
连接地址可以是NULL,表示由系统自动选择一个合适的地址。
连接成功后,shmat函数返回一个指向共享内存段的指针,进程可以通过该指针来访问共享内存段中的数据。
当进程不再需要访问共享内存段时,可以调用shmdt函数来断开与共享内存段的连接。
该函数接受一个参数,即共享内存段的指针。
断开连接后,进程将无法再访问共享内存段中的数据。
最后,当所有进程都断开与共享内存段的连接后,可以调用shmctl 函数来控制共享内存段的状态。
该函数接受三个参数,分别是共享内存段的标识符、命令和一个可选的参数。
命令可以是IPC_RMID,表示删除共享内存段。
删除共享内存段后,所有与之相关的连接将自动断开。
通过上述的系统调用函数,Linux实现了内存共享的机制。
多个进程可以通过共享内存段来共享数据,从而避免了数据的复制和传输,提高了系统的性能和资源利用率。
同时,Linux还提供了一些机制,如信号量和互斥锁,用于控制对共享内存段的并发访问,保证数据的一致性和完整性。
共享存储区进程通信代码示例
1. /*server.c:向共享内存中写入People*/2. #include <stdio.h>3. #include <sys/types.h>4. #include <sys/ipc.h>5. #include <sys/sem.h>6.7. int main()8. {9. struct People{10. char name[10];11. int age;12. };13.14. int semid;15. int shmid;16. key_t semkey;17. key_t shmkey;18. semkey=ftok("server.c",0);//把文件读入共享存储区里,需要用key_t key=ftok();19. shmkey=ftok("client.c",0);20.21. /*创建共享内存和信号量的IPC*/22. semid=semget(semkey,1,0666|IPC_CREAT);23. if(semid==-1)24. printf("creat sem is fail/n");25. shmid=shmget(shmkey,1024,0666|IPC_CREAT);26. if(shmid==-1)27. printf("creat shm is fail/n");28.29. /*设置信号量的初始值,就是资源个数*/30. union semun{31. int val;32. struct semid_ds *buf;33. ushort *array;34. }sem_u;35.36. sem_u.val=1;37. semctl(semid,0,SETVAL,sem_u);38.39. /*将共享内存映射到当前进程的地址中,之后直接对进程中的地址addr操作就是对共享内存操作*/40.41. struct People * addr;42. addr=(struct People*)shmat(shmid,0,0);43. if(addr==(struct People*)-1)44. printf("shm shmat is fail/n");45.46. /*信号量的P操作*/47. void p()48. {49. struct sembuf sem_p;50. sem_p.sem_num=0;51. sem_p.sem_op=-1;52. if(semop(semid,&sem_p,1)==-1)53. printf("p operation is fail/n");54. }55.56. /*信号量的V操作*/57. void v()58. {59. struct sembuf sem_v;60. sem_v.sem_num=0;61. sem_v.sem_op=1;62. if(semop(semid,&sem_v,1)==-1)63. printf("v operation is fail/n");64. }65.66. /*向共享内存写入数据*/67. p();68. strcpy((*addr).name,"xiaoming");69. /*注意:①此处只能给指针指向的地址直接赋值,不能在定义一个 struct People people_1;addr=&people_1;因为addr在addr=(struct People*)shmat(shmid,0,0);时,已经由系统自动分配了一个地址,这个地址与共享内存相关联,所以不能改变这个指针的指向,否则他将不指向共享内存,无法完成通信了。
用共享内存实现消息队列
用共享内存实现消息队列共享内存是一种特殊的内存区域,它允许两个或多个进程访问相同的内存空间,从而实现数据的共享。
在实际应用中,可以使用共享内存实现高效的消息队列,提高进程间通信的性能。
本文将介绍如何使用共享内存实现消息队列。
1. 创建共享内存区域:首先,需要创建一个共享内存区域,用于存储消息数据。
可以使用系统调用shmget来创建共享内存区域,并通过参数指定共享内存的大小。
```c#include <sys/ipc.h>#include <sys/shm.h>key_t key = ftok("keyfile", 'A'); // 生成一个key,用于标识共享内存区域int shm_id = shmget(key, size, IPC_CREAT , 0666); // 创建共享内存区域,并指定大小```2. 连接共享内存区域:创建共享内存区域后,需要通过指定的shm_id来连接到该区域,并获得指向该内存区域的指针。
```cvoid* shm_ptr = (void*)shmat(shm_id, NULL, 0); // 连接共享内存区域,并返回指向该区域的指针```3.定义消息结构体:在共享内存区域中,可以定义一个消息结构体,用于存储消息的内容。
```ctypedef structint type; // 消息类型char data[256]; // 消息数据} Message;```4.实现消息队列的操作:在共享内存区域中,可以定义一个变量来作为指示消息队列状态的变量,比如当前队列中的消息数量。
使用互斥锁或信号量来保护队列的并发操作。
```c#define MAX_MESSAGES 10typedef structint count; // 消息数量int front; // 队列头int rear; // 队列尾Message messages[MAX_MESSAGES]; // 消息队列数组} MessageQueue;void push(MessageQueue* queue, Message msg)//加锁//将消息添加到队列尾部//更新队列头和尾//解锁Message pop(MessageQueue* queue)//加锁//获取队列头的消息//更新队列头指针//解锁return message;```5. 使用消息队列:在多个进程中,可以使用共享内存区域实现的消息队列进行进程间通信。
关于共享内存涉及到的四个函数
关于共享内存涉及到的四个函数共享内存是一种用于多进程间通讯的技术,它允许多个进程共享同一块内存区域,从而实现数据交换和互相通信。
在使用共享内存时,我们需要掌握一些相关的函数,以下是涉及到的四个函数:1. shmget函数shmget函数用于创建共享内存,它的原型为:```int shmget(key_t key, size_t size, int shmflg);```其中,key是共享内存的关键字,size是共享内存的大小,shmflg 是创建共享内存时的选项。
该函数返回一个共享内存标识符(shmid),它是在共享内存创建成功后用于标识该共享内存的唯一标识符。
2. shmat函数shmat函数用于将共享内存连接到当前进程的地址空间,它的原型为:```void *shmat(int shmid, const void *shmaddr, int shmflg); ```其中,shmid是共享内存的标识符,shmaddr是连接的地址,如果shmaddr为NULL,则由系统选择一个合适的地址。
该函数返回一个指向共享内存第一个字节的指针,如果连接失败,则返回-1。
3. shmdt函数shmdt函数用于将共享内存从当前进程的地址空间分离,它的原型为:```int shmdt(const void *shmaddr);```其中,shmaddr是共享内存的地址,该函数返回0表示成功,返回-1表示失败。
4. shmctl函数shmctl函数用于对共享内存进行控制操作,它的原型为:```int shmctl(int shmid, int cmd, struct shmid_ds *buf); ```其中,shmid是共享内存的标识符,cmd是控制命令,buf是用于存储共享内存状态信息的结构体。
该函数返回0表示成功,返回-1表示失败。
以上四个函数是使用共享内存时必须掌握的关键函数,它们共同构成了共享内存的基本操作。
shmget函数
shmget函数```c#include <sys/ipc.h>#include <sys/shm.h>int shmget(key_t key, size_t size, int shmflg);```参数说明:- `key`:共享内存段的唯一标识符。
通常使用ftok函数根据一个已存在的文件来生成key,也可以使用IPC_PRIVATE来创建一个只能用于亲缘关系的进程之间通信的共享内存段。
- `size`:共享内存段的大小,以字节为单位。
- `shmflg`:标志位,用于设置共享内存段的权限和操作方式。
常用的标志有IPC_CREAT(如果不存在,则创建新的共享内存段)、IPC_EXCL (结合IPC_CREAT使用,如果共享内存段已存在,则返回错误)、SHM_RDONLY(以只读方式打开共享内存段)等。
函数返回值是一个非负的整数,表示共享内存段的标识符(内核中的索引值),用于其他系统调用对共享内存段的操作。
共享内存在创建后会存在于内核中,但是在进程中并不直接可见,需要通过其他函数将共享内存映射为进程的地址空间,才能对其进行读写操作。
下面是一个简单的示例,展示如何使用shmget函数创建一个共享内存段:```c#include <sys/ipc.h>#include <sys/shm.h>#include <stdio.h>#include <stdlib.h>int maikey_t key = ftok("/tmp", 'A'); // 生成一个keyint shm_id = shmget(key, 1024, IPC_CREAT,0666); // 创建一个大小为1024字节的共享内存段if (shm_id == -1)perror("shmget");exit(1);}printf("Shared memory segment ID: %d\n", shm_id);return 0;```运行上述代码后,会创建一个大小为1024字节的共享内存段,并打印出共享内存段的标识符。
Unix下共享内存及信号量的使用
Unix下共享内存及信号量的使用Unix下共享内存的使用,要考虑内存的开辟及存取。
存取共享内存要用信号量机制避免并行操作。
下面就共享内存块及信号量配合操作做了说明。
1、相关结构体#define USER_SHM_FILE "/tmp/ShmFile.dat"#define SHM_SIZE 32#define SMem_NUM 4 //共享内存块的个数typedef struct{unsigned char *pRead;unsigned char *pWrite;}UserShareMem;UserShareMem MyShm[SMem_NUM];int MyShmId[SMem_NUM ] ; //共享内存标识符int MySemId[SMem_NUM] ; //对应的存取信号量union semun{int val;struct semid_ds * buf;ushort * array;};2、共享块相关操作2.1 函数封装设计int CreateSham(int mem_index,int msize){key_t key ;int shm_fd = 0 ;if( (shm_fd = open(USER_SHM_FILE, O_RDWR)) < 0 ){shm_fd = open(USER_SHM_FILE, O_RDWR|O_CREAT, S_IRWXU);if(shm_fd<0){printf("Create %s failed \n",USER_SHM_FILE);return 0 ;}}if(shm_fd>0)close(shm_fd);key = ftok(USER_SHM_FILE, mem_index) ;MyShmId[mem_index] = shmget(key, msize, SVSHM_MODE | IPC_CREAT);MyShm[mem_index].pRead = shmat(MyShmId[mem_index], NULL, 0);MyShm[mem_index].pWrite = shmat(MyShmId[mem_index], NULL, 0);MySemId[mem_index] = create_sem(key);return 1 ;}2.2 函数解读首先用open打开文件,然后ftok获取id值。
- 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 ;