Linux IPC之共享内存

System V共享内存机制: shmget  shmat  shmdt  shmctl

原理及实现:

system V IPC机制下的共享内存本质是一段特殊的内存区域,进程间需要共享的数据被放在该共享内存区域中,所有需要访问该共享区域的进程都要把该共享区域映射到本进程的地址空间中去。这样一个使用共享内存的进程可以将信息写入该空间,而另一个使用共享内存的进程又可以通过简单的内存读操作获取刚才写入的信息,使得两个不同进程之间进行了一次信息交换,从而实现进程间的通信。

共享内存允许一个或多个进程通过同时出现在它们的虚拟地址空间的内存进行通信,而这块虚拟内存的页面被每个共享进程的页表条目所引用,同时并不需要在所有进程的虚拟内存都有相同的地址。进程对象对于共享内存的访问通过key(键)来控制,同时通过key进行访问权限的检查。

函数定义如下:

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

key_t ftok(const char *pathname, int proj_id);

函数ftok用于创建一个关键字,可以用该关键字关联一个共享内存段。

参数pathname为一个全路径文件名,并且该文件必须可访问。

参数proj_id通常传入一非0字符

通过pathname和proj_id组合可以创建唯一的key

如果调用成功,返回一关键字,否则返回-1

 

int shmget(key_t key, int size, int shmflg);

函数shmget用于创建或打开一共享内存段,该内存段由函数的第一个参数唯一创建。函数成功,则返回一个唯一的共享内存标识号(相当于进程号,唯一的标识着共享内存),失败返回-1。

参数key是一个与共享内存段相关联关键字,如果事先已经存在一个与指定关键字关联的共享内存段,则直接返回该内存段的标识,表示打开,如果不存在,则创建一个新的共享内存段。key的值既可以用ftok函数产生,也可以是IPC_RPIVATE(用于创建一个只属于创建进程的共享内存,主要用于父子通信),表示总是创建新的共享内存段;

参数size指定共享内存段的大小,以字节为单位;

参数shmflg是一掩码合成值,可以是访问权限值与(IPC_CREAT或IPC_EXCL)的合成。IPC_CREAT表示如果不存在该内存段,则创建它。IPC_EXCL表示如果该内存段存在,则函数返回失败结果(-1)。如果调用成功,返回内存段标识,否则返回-1

 

void *shmat(int shmid, const void *shmaddr, int shmflg);

函数shmat将共享内存段映射到进程空间的某一地址

参数shmid是共享内存段的标识  通常应该是shmget的成功返回值

参数shmaddr指定的是共享内存连接到当前进程中的地址位置。通常是NULL,表示让系统来选择共享内存出现的地址。

参数shmflg是一组位标识,通常为0即可。

如果调用成功,返回映射后的进程空间的首地址,否则返回(char *)-1。

 

int shmdt(const void *shmaddr);

函数shmdt用于将共享内存段与进程空间分离

参数shmaddr通常为shmat的成功返回值。

函数成功返回0,失败时返回-1.注意,将共享内存分离并没删除它,只是使得该共享内存对当前进程不在可用。

 

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

函数shmctl是共享内存的控制函数,可以用来删除共享内存段

参数shmid是共享内存段标识 通常应该是shmget的成功返回值

参数cmd是对共享内存段的操作方式,可选为IPC_STAT,IPC_SET,IPC_RMID。通常为IPC_RMID,表示删除共享内存段。

参数buf是表示共享内存段的信息结构体数据,通常为NULL

例如shmctl(kshareMem,IPC_RMID,NULL)表示删除调共享内存段kHareMem

示例:

shm1.c

 

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string.h>
 4 #include<unistd.h>
 5 #include<sys/types.h>
 6 #include<sys/ipc.h>
 7 #include<sys/shm.h>
 8 
 9 int main(int *argc, char *argv[])
10 {
11     key_t my_key;
12     int my_shm;
13     char *pstr;
14 
15     //1,创建一个关键字,使其关联一个共享内存段,返回关键字
16     my_key = ftok("./temp.c",123);
17 
18     //2,创建或打开一个共享内存段,返回共享内存段标志号
19     my_shm = shmget(my_key,1024,0666 | IPC_CREAT);
20     if(my_shm == -1)
21     {
22         printf("shmget error!\n");
23         exit(1);
24     }
25 
26     //3,将共享内存段映射到进程空间的某一地址,返回映进程射空间的首地址
27     pstr =  (char*)shmat(my_shm,NULL,0);
28 
29     strcpy(pstr,"Hello world!\n");
30     sleep(5);
31     printf("recv from 2:%s\n",pstr);
32 
33     //4,将共享内存段与进程空间分离
34     shmdt(pstr);
35 
36     //5,删除共享内存段
37     shmctl(my_shm,IPC_RMID,NULL);    
38 
39     return 0;
40 }

 

shm2.c

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string.h>
 4 #include<unistd.h>
 5 #include<sys/types.h>
 6 #include<sys/ipc.h>
 7 #include<sys/shm.h>
 8 
 9 int main(int *argc, char *argv[])
10 {
11     key_t my_key;
12     int my_shm;
13     char *pstr;
14 
15     //1,创建关键字
16     my_key = ftok("./temp.c",123);
17 
18     //2,创建或打开共享内存段
19     my_shm = shmget(my_key,1024,0666);
20     if(my_shm == -1)
21     {
22         printf("Shmget error!\n");
23         exit(1);
24     }
25 
26     //3,将共享内存段映射到某一进程空间
27     pstr = (char*)shmat(my_shm,NULL,0);
28     printf("recv from 1:%s\n",pstr);
29     strcpy(pstr,"How are you!\n");
30 
31     //4将共享内存段与进程空间分离
32     shmdt(pstr);
33     
34     return 0;
35 }

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。