共享内存为多个进程之间共享和传递数据提供了一种有效的方式,未提供同步机制,我们需要用其他的机制来同步对共享内存的访问。
共享内存使用的函数:
#include <sys/shm.h>
void *shmat(int shm_id,const void *shm_addr,int shmflg);
第一次创建共享内存段时,它不能被任何进程访问,要想启用对该共享内存的访问,必须将其连接到一个进程的地址空间中。这项工作由shmat函数完成。shm_addr指定的是共享内存连接到当前进程中的地址位置,通常是一个空指针。
int shmctl(int shm_id,int cmd,struct shmid_ds *buf);
int shmdt(const void *shm_addr);将共享内存从当前进程中分离,它的参数是shmat返回的地址指针
int shmget(key_t key,size_t size,int shmflg); 创建共享内存,返回共享内存标识符。
shm1.c
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<sys/shm.h>
#include "shm_com.h"
int main()
{
int running =1;
void *shared_memory=(void *)0;
struct shared_use_st *shared_stuff;
int shmid;
srand((unsigned int)getpid());
shmid=shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);
if(shmid==-1)
{
fprintf(stderr,"shmget failed\n");
exit(EXIT_FAILURE);
}
//现在让程序可以访问共享内存
shared_memory=shmat(shmid,(void *)0,0);
if(shared_memory==(void *)-1)
{
fprintf(stderr,"shmat failed\n");
exit(EXIT_FAILURE);
}
printf("Memory attached at %X\n",(int)shared_memory);
//将shared_memory分配给shared_stuff,然后它输出written_by_you中的文本
shared_stuff=(struct shared_use_st *)shared_memory;
shared_stuff->written_by_you=0;
while(running)
{
if(shared_stuff->written_by_you)
{
printf("You wrote: %s",shared_stuff->some_text);
sleep(rand()%4);
shared_stuff->written_by_you=0;
if(strncmp(shared_stuff->some_text,"end",3)==0)
running=0;
}
}
//最后,共享内存被分离,然后被删除
if(shmdt(shared_memory)==-1)
{
fprintf(stderr,"shmdt failed\n");
exit(EXIT_FAILURE);
}
if(shmctl(shmid,IPC_RMID,0)==-1)
{
fprintf(stderr,"shmctl(IPC_RMID) failed\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
shm2.c
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<sys/shm.h>
#include"shm_com.h"
int main()
{
int running=1;
void *shared_memory=(void *)0;
struct shared_use_st *shared_stuff;
char buffer[BUFSIZ];
int shmid;
shmid=shmget((key_t)1234,sizeof(struct shared_use_st),0666|IPC_CREAT);
if(shmid==-1)
{
fprintf(stderr,"shmget failed\n");
exit(EXIT_FAILURE);
}
shared_memory=shmat(shmid,(void *)0,0);
if(shared_memory==(void *)-1)
{
fprintf(stderr,"shmat failed\n");
exit(EXIT_FAILURE);
}
printf("Momery attached at %X\n",(int)shared_memory);
shared_stuff=(struct shared_use_st *)shared_memory;
while(running)
{
while(shared_stuff->written_by_you==1)
{
sleep(1);
printf("waiting for client...\n");
}
printf("Enter some text: ");
fgets(buffer,BUFSIZ,stdin);
strncpy(shared_stuff->some_text,buffer,TEXT_SZ);
shared_stuff->written_by_you=1;
if(strncmp(buffer,"end",3)==0)
running=0;
}
if(shmdt(shared_memory)==-1)
{
fprintf(stderr,"shmdt failked\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
第一个程序shm1创建共享内存段,然后将它链接到自己的地址空间中,我们在共享内存的开始处使用了一个结构shared_use_st,该结构中有个标志written_by_you,当共享内存中有数据写入时,就设置这个标志。这个标志被设置时,程序就从内存中读取文本,将它打印出来,然后清除这个标志表示已经读完数据,用end来退出循环。接下来程序分离共享内存段并删除它。
shm2使用相同的键1234来取得并连接同一个共享内存段。然后提示用户输入一些文本。如果标志written_by_you被设置,shm2就知道客户进程还没有读完上一次数据,因此就继续等待,当其他进程清除了这个标志,shm2写入新数据并设置该标志。它还使用end来终止,并分离共享内存段。
这里我们使用非常简陋的written_to_you同步标志进行忙等,不是一种好方法。