相关函数
1.创建共享内存shmget
原型:int shmget(key_t key, size_t size, int shmflg)返回值: 创建成功,则返回一个非负整数,即共享内存标识; 如果失败,则返回-1.
参数:
key: //程序需要提供一个参数key,它为共享内存段提供一个外部名。(每个IPC对象都与一个键 即key相关联,然后此键再由内核变换为标识符)。还有一个特殊的键值IPC_PRIVATE, 它用于创建一个只属于该创建进程的新共享内存,通常不会用到;
该函数原型:void *shmat(int shmid, const void *shmaddr, int shmflg) 返回值:调用成功返回挂载的虚拟地址空间起始地址,失败返回NULL
参数:
int shmid //是由shmget函数返回的共享内存标识。
const void *shmaddr //指定共享内存连接到当前进程中的地址位置,通常为0,表示让系统来选择 共享内存的地址。
int shmflg //是一组标志位,通常为0。它还可取:SHM_RND,用以决定是否将当前共享内存段连接到指定的shmaddr上。该参数和shm_addr联合使用,用来控制共享内存连接的地址,除非只计划在一种硬件上运行应用程序,否则不要这样指定。填0让操作系统自己选择是更好的方式。
SHM_RDONLY单独使用则是指让它使连接的内存段只读,否则以读写方式连接此内存段
3. 与共享内存段分离 shmdt
原型:int shmdt(const void *shmaddr)
参数:
只是使得该共享内存对当前进程不再可用。
4. shmctl 共享内存控制函数
#include#include 原型: int shmctl(int shmid, int cmd, struct shmid_ds *buf)
参数:
struct shmid_ds { uid_t shm_perm.uid; uid_t shm_perm.gid; mode_t shm_perm.mode; }
简单使用
简单用共享内存来再两进程间交换数据,比如交换一个结构体
代码如下:
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 typedef struct Stu 8 { 9 int age;10 char name[10];11 }Stu;12 13 int main( void)14 { 15 Stu s;16 strcpy(s.name, "jack");17 //创建共享内存段18 int id = shmget(1234, 8, IPC_CREAT|0644);19 if( id == -1)perror( " shmget"),exit( 1);20 //挂载到进程的地址空间21 Stu* p = ( Stu*)shmat( id, NULL, 0);22 23 int i =0;24 while( 1)25 { 26 s.age = i++;27 memcpy(p, &s, sizeof(Stu)); //写到共享段中28 sleep( 2);29 }30 return 0;31 }
1 #include2 #include 3 #include 4 #include 5 #include 6 typedef struct Stu 7 { 8 int age; 9 char name[10];10 }Stu;11 int main( void)12 { 13 int id = shmget(1234, 8, 0);14 if( id == -1)perror( " shmget"),exit( 1);15 16 Stu* p = ( Stu*)shmat( id, NULL, 0);17 while( 1)18 { 19 printf(" age= %d, name= %s\n", p->age, p->name);20 sleep(2);21 }22 return 0;23 }
执行结果如下:
小结
优点:我们可以看到使用共享内存进行进程间的通信真的是方便而高效,而且函数的接口也简单,数据的共享还使进程间的数据不用传送,而是直接访问内存,也加快了程序的效率。同时,它也不像匿名管道那样要求通信的进程有一定的父子关系。
上面只是共享内存的一些简单的应用,当多个进程对共享内存进行访问时,并没有保证同步,所以我们还需要用其它的机制来实现它的同步机制,要解决此,通常会用到信号量(PV操作)来实现。但要基于此的实现,前提还需要熟悉信号量的操作以及这里的共享内存使用。要用共享内存模拟做出一个带同步机制"先进先出"的消息通道,对我等萌新并不太容易,所以还得放到以后再实现了。。