现在的位置: 首页 > 综合 > 正文

linux 进程间通信(IPC)一共享内存

2014年01月29日 ⁄ 综合 ⁄ 共 2839字 ⁄ 字号 评论关闭

共享内存为多个进程之间共享和传递数据提供了一种有效的方式,未提供同步机制,我们需要用其他的机制来同步对共享内存的访问。


共享内存使用的函数:

#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同步标志进行忙等,不是一种好方法。

抱歉!评论已关闭.