相关函数
1.创建共享内存shmget
原型:int shmget(key_t key, size_t size, int shmflg) 返回值: 创建成功,则返回一个非负整数,即共享内存标识; 如果失败,则返回-.
参数:
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 <sys/ipc.h>
#include <sys/shm.h> 原型: 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;
}
简单使用
简单用共享内存来再两进程间交换数据,比如交换一个结构体
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
typedef struct Stu
{
int age;
char name[];
}Stu; int main( void)
{
Stu s;
strcpy(s.name, "jack");
//创建共享内存段
int id = shmget(, , IPC_CREAT|);
if( id == -)perror( " shmget"),exit( );
//挂载到进程的地址空间
Stu* p = ( Stu*)shmat( id, NULL, ); int i =;
while( )
{
s.age = i++;
memcpy(p, &s, sizeof(Stu)); //写到共享段中
sleep( );
}
return ;
}
write.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
typedef struct Stu
{
int age;
char name[];
}Stu;
int main( void)
{
int id = shmget(, , );
if( id == -)perror( " shmget"),exit( ); Stu* p = ( Stu*)shmat( id, NULL, );
while( )
{
printf(" age= %d, name= %s\n", p->age, p->name);
sleep();
}
return ;
}
read.c
执行结果如下:
小结
优点:我们可以看到使用共享内存进行进程间的通信真的是方便而高效,而且函数的接口也简单,数据的共享还使进程间的数据不用传送,而是直接访问内存,也加快了程序的效率。同时,它也不像匿名管道那样要求通信的进程有一定的父子关系。
上面只是共享内存的一些简单的应用,当多个进程对共享内存进行访问时,并没有保证同步,所以我们还需要用其它的机制来实现它的同步机制,要解决此,通常会用到信号量(PV操作)来实现。但要基于此的实现,前提还需要熟悉信号量的操作以及这里的共享内存使用。要用共享内存模拟做出一个带同步机制"先进先出"的消息通道,对我等萌新并不太容易,所以还得放到以后再实现了。。