共享内存为多个进程之间共享和传递数据提供了一种有效的方式,未提供同步机制,我们需要用其他的机制来同步对共享内存的访问。
共享内存使用的函数:
#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同步标志进行忙等,不是一种好方法。