两个进程共享内存,一个写,一个读

要求是:生产者进程生成Catalan序列,并将其写入到内存共享对象。消费者进程从共享内存中读取并输出序列。生产者进程要在命令行指定生成Catalan数的数目。例如,命令行指定5,说明生产者进程会生成5个Catalan数:1   2   5   14   42

这里的实现没有显式创建进程,因为打开不同的命令行窗口就于创建新进程。

//生产者(write)
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define MAX 32 
void *pAddr;
int shmId;
 
struct Msg{
  int flag;//0为读,1为写
  long long content[MAX];
};                          //content:存catalan数   flag:共享内存占用标志的信号
 
void Handle(int s){
  if(s == 2)
  {
     //本函数调用并不删除所指定的共享内存区,而只是将先前用shmat函数连接(attach)好的共享内存脱离(detach)目前的进程
     shmdt(pAddr);     
     shmctl(shmId,IPC_RMID,0);  //完成对共享内存的控制,删除这片共享内存
     exit(0);
  }
} 
 


int main(){
  int n = 0;    //Catalan数的数目
  int i=0,j=0;
	
  
  /*
     按ctrl+c键退出时会处理这个消息,进行共享内存卸载、删除操作(handle功能),最后exit(0)退出程序
     signal函数和书上的信号量signal不一样,这里的功能使调用handle函数并把2作为handle的参数
  */
  signal(2,Handle);

  /*
    key_t ftok(char *fname,int id)将一个已存在的路径名和一个整数标识符转换成一个key_t值
    得到IPC通信的key,用于创建共享内存。"."表示文件名为当前目录,按照ftok的规则,由于我的read程 
    序也在当前目录,使用的ftok函数的参数相同,因此得到的key也相同
  */
  key_t key = ftok(".",2);
 
  /* 
     创建共享内存,shmId是共享内存标识符
     100表示申请的共享内存是100字节;IPC_CREAT | IPC_EXCL | 0666 :前两个保证创建新内存,否则返            
     回值为-1,0666是3位八进制数,6即二进制110,表示可读可写不可执行,从左到右分别对应当前用户, 
     group组用户,其他用户
  */  
  shmId = shmget(key,100,IPC_CREAT | IPC_EXCL | 0666); 

  pAddr = shmat(shmId,0,0);  //把共享内存区对象映射到调用进程的地址空间,随后可像本地地址空间一样进行访问,第二个参数指定为0让内核决定内存的位置,第三个参数0表示可读写
 
  if(*(int *)pAddr == -1){
    printf("shmat error!\n"); 
    exit(0);
  }
 
 
  memset(pAddr,0,100); //将pAddr处的100个字节设置为NULL
  struct Msg *msg = (struct Msg *)pAddr; //msg 指向共享内存
  msg->flag = 1;       //表示写进程占用共享内存
  while(1){
    if(msg->flag == 1){//当为1时写消息,此时读文件中不能操作此共享内存
      i=0;  
      for(i=0;icontent[i]=0;    //初始化

      printf("The number of catalan:");
      scanf("%d",&n);
      msg->content[0] = 1;
      for(j=1;jcontent[j] = msg->content[j-1]*(4*j+2)/(j+2); //计算Catalan数

      msg->flag = 0;//当写消息后flag置为0,让读文件开始执行读操作,此时写文件不能进行写操作
    }
    else{
      sleep(1);        //停止1s,让读进程读取msg指向的数据(共享内存)并输出
    }
  }
  return 0;
}

 

//消费者(read)
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define MAX 32
 
void *pAddr;
int shmId;
 
struct Msg{
  int flag;
  long long content[MAX];
};
 
int main(){
  int i=0;
  key_t key = ftok(".",2);
  shmId = shmget(key,0,0); //key与writed的key相同,后两个0表示获取该共享内存
  
  pAddr = shmat(shmId,0,0); //获取共享内存的地址
 
  if(*(int *)pAddr == -1){
    printf("shmat error!\n"); 
    exit(0);
  }
  
  struct Msg * msg = (struct Msg *)pAddr;
  while(1){
      if(msg->flag == 0){//当为0时读消息,此时写文件中不能操作此共享内存
      i=0;
      while(msg->content[i]!=0)
      {
           printf("%lld\n",msg->content[i]);
           i++;
      }

      msg->flag = 1;
    }
    else{
      sleep(1); 
    }
  } 
  
  return 0;
}

本文参考

参考源码  https://blog.csdn.net/qq_29762941/article/details/79985377

共享内存函数 https://blog.csdn.net/guoping16/article/details/6584058

signal()函数 https://blog.csdn.net/chenjianqi0502/article/details/78579541

shmget的参数https://blog.csdn.net/ec06cumt/article/details/51444961   https://blog.csdn.net/Fly_as_tadpole/article/details/81044096

ftok()函数

https://www.cnblogs.com/joeblackzqq/archive/2011/05/31/2065161.html  https://www.cnblogs.com/HectorInsanE/archive/2011/03/17/1986859.html

你可能感兴趣的:(算法)