通过共享内存,利用循环队列实现两个进程A,B之间的通信

        对我来说,这是一个艰难的程序,花了好长时间,才真正完成,对一个初学者

来说,可以学到很多。

进程A:

#include    <sys/types.h> 
#include    <sys/ipc.h> 
#include    <sys/shm.h> 
#include    <stdio.h> 
#include    <error.h>
#include    <stdlib.h>
#include    <string.h>


#define SHM_SIZE    4096 


typedef struct
{
  int front;
  int rear;
  int data[10];
}sq;

 

/*函数功能: 初始化循环队列*/
int init_seq_queue(sq *Q)
{

 Q->front = 0; 
 Q->rear = 0;
 memset(Q->data,0,sizeof(int)*10);
 return ;
}

int enqueue (sq *Q,int num)
{
 if((Q->rear+1)%10 == Q->front)
 {
  return -1;
 }
 else
 {
  Q->data[Q->rear]=num;
  Q->rear=(Q->rear+1)%10;
  return 0;
 }
}

 

int main()
{
 //sq Q;
 int i;
 //int num;
 int a[9];


 int shmid;
 char *shmptr;
 sq *pnode;
   

 shmid=shmget(0x20,SHM_SIZE,IPC_CREAT|0600);
  if(shmid==-1)
  {
   printf("出错了。\n");
   return -1;
  }
  printf("shmid=%d\n",shmid);

 shmptr=shmat(shmid, NULL, 0);
 
 if ( shmptr == (void *) -1)
  {
   printf("出错了");
   return -1;
  }
 
 pnode = (sq *)shmptr;
 
 init_seq_queue(pnode);

 scanf("%d%d%d%d%d%d%d%d%d",&a[0],&a[1],
  &a[2],&a[3],&a[4],&a[5],&a[6],&a[7],&a[8]);
 printf("这组数据为:%d,%d,%d,%d,%d,%d,%d,%d,%d\n",a[0],a[1],
 a[2],a[3],a[4],a[5],a[6],a[7],a[8]);
 
 for(i=0;i<9;i++)
 {
  if(enqueue(pnode,a[i])==-1)
   return 0;
 }

 
 /*
 for(i=0;i<9;i++)
 {
  scanf("%d ",&a[i]);
  if(enqueue(pnode,a[i])==-1)
   return 0;
 }
 */
 
 /*
 for(i=0;i<9;i++)
 {
        enqueue(pnode,i);
  printf("%d\n",i);
 }
 */
 
}

进程B:

#include    <sys/types.h> 
#include    <sys/ipc.h> 
#include    <sys/shm.h> 
#include    <stdio.h> 
#include    <error.h>
#include    <stdlib.h>
#include    <string.h>

#include    <malloc.h>

#define SHM_SIZE  4096
#define SHM_MODE    (SHM_R | SHM_W)

typedef struct
{
  int front;
  int rear;
  int data[10];
}sq;

int dequeue (sq *Q, int *num)
{
 if(Q->front==Q->rear)
  return -1;
 else
 {
  *num=Q->data[Q->front];
  Q->front=(Q->front+1)%10;
  return 0;
 }
}


int main()
{
 int shmid;
 char *shmptr;

 
 int num;
 sq *pnode;

 

 shmid=shmget(0x20,SHM_SIZE,IPC_CREAT|0600);
  if(shmid==-1)
  {
   printf("出错了。\n");
   return -1;
  }
  printf("shmid=%d\n",shmid);
  
 shmptr=shmat(shmid, NULL, 0);
 
 if ( shmptr == (void *) -1)
  {
   printf("出错了\n");
   return -1;
  }
 
 pnode=(sq *)shmptr;

 while(1)
 {
  sleep(1);
     if(dequeue(pnode,&num)==0)
     {
      printf("到这了。。。");
   printf(" the number is %d\n",num);
     }
  //memset(pnode,0x00,sizeof(sq));
 }

 exit(0);

}

 

      现在具体来讲一下这两个进程,A进程通过自定义一个循环队列,在这里没有用到自动分配

内存,在结构体当中直接定义了一个大小为十的整型数组。并且在A,B两个进程中,我把没有用

到的函数删除了,这样使得代码更加简单。

      在这里我讲述几个我在写这个程序时碰到的问题。

      1.memset()函数的使用,比如在进程A中的这一句,memset(Q->data,0,sizeof(int)*10); 它是

对结构体中的data数组进行初始化,为什么还要*10?因为你在结构体中定义的整型data数组大小为

10.

 

      2.scanf函数,在这当中碰到这么一个问题,比如下面一段小程序:

#include <stdio.h>

int main()

{

int a,b;

printf("请从键盘输入两个整数:");

scanf("%d%d\n",&a,&b);//或者scanf("%d%d ",&a,&b);

printf("a=%d,b=%d\n");

}

     运行程序,你输入两个数时,并不算结束,而是要再次输入另外一个数才算结束,这是因为空白

结尾时,scanf会跳过空白,去读下一个数。

 

       3.sq*pnode,这是我定义的一个结构体指针。pnode=(sq *)shmptr;当程序执行到这一句时,

实际上在共享内存中已经建立起了这样一个模型的结构体。

 

       下面再贴两段代码,暂且命名为A1,B1吧,他们的功能与上面的是一样的,只不过在上面两段

是在A中写入整型,B中读出整型,而下面的是写入字符串而已。

进程A1:

#include    <sys/types.h> 
#include    <sys/ipc.h> 
#include    <sys/shm.h> 
#include    <stdio.h> 
#include    <error.h>
#include    <stdlib.h>
#include    <string.h>

#define SHM_SIZE    4096 

 


typedef struct
{
  int front;
  int rear;
  char data[10];
  int sign;
}sq;

 

 

/*函数功能: 初始化循环队列*/
int init_seq_queue(sq *Q)
{

 Q->front = 0; 
 Q->rear = 0;
 memset(Q->data,0,sizeof(char));
 return ;
}

int enqueue (sq *Q,char s)
{
 if((Q->rear+1)%10 == Q->front)
 {
  return -1;
 }
 else
 {
  Q->data[Q->rear]=s;
  Q->rear=(Q->rear+1)%10;
  return 0;
 }
}

int dequeue (sq *Q, char *s)
{
 if(Q->front==Q->rear)
  return -1;
 else
 {
  *s=Q->data[Q->front];
  Q->front=(Q->front+1)%10;
  return 0;
 }
}

int main()
{
 //sq Q;
 int i,length;
 //int num;
 char a[10];


 int shmid;
 char *shmptr;
 sq *pnode;
   

 shmid=shmget(0x32,SHM_SIZE,IPC_CREAT|0600);
  if(shmid==-1)
  {
   printf("shmget 出错了。\n");
   return -1;
  }
  printf("shmid=%d\n",shmid);

 shmptr=shmat(shmid, NULL, 0);
 
 if ( shmptr == (void *) -1)
  {
   printf("shmat 出错了。\n");
   return -1;
  }
 
 pnode = (sq *)shmptr;
 
 init_seq_queue(pnode); //指针会根据结构体自动按照其规定分配

 printf("请输入一串字符串:");
 scanf("%s",a);
 printf("数组a是:%s\n",a);
 length=strlen(a);
 printf("length is %d\n",length);
 for(i=0;i<length;i++)
 {
  printf("到否?\n");
  if(enqueue(pnode,a[i])==-1)
   return 0;
 }
 
 
}

进程B1:

#include    <sys/types.h> 
#include    <sys/ipc.h> 
#include    <sys/shm.h> 
#include    <stdio.h> 
#include    <error.h>
#include    <stdlib.h>
#include    <string.h>

#define SHM_SIZE    4096 

 


typedef struct
{
  int front;
  int rear;
  char data[10];
  int sign;
}sq;

 

 

/*函数功能: 初始化循环队列*/
int init_seq_queue(sq *Q)
{

 Q->front = 0; 
 Q->rear = 0;
 memset(Q->data,0,sizeof(char));
 return ;
}

int enqueue (sq *Q,char s)
{
 if((Q->rear+1)%10 == Q->front)
 {
  return -1;
 }
 else
 {
  Q->data[Q->rear]=s;
  Q->rear=(Q->rear+1)%10;
  return 0;
 }
}

int dequeue (sq *Q, char *s)
{
 if(Q->front==Q->rear)
  return -1;
 else
 {
  *s=Q->data[Q->front];
  Q->front=(Q->front+1)%10;
  return 0;
 }
}

int main()
{
 char a;
 /*char a[10];假设这边用的是这个类型,那么
 4中也应该是这种类型*/

 int shmid;
 char *shmptr;
 sq *pnode;
   

 shmid=shmget(0x32,SHM_SIZE,IPC_CREAT|0600);
  if(shmid==-1)
  {
   printf("shmget 出错了。\n");
   return -1;
  }
  printf("shmid=%d\n",shmid);

 shmptr=shmat(shmid, NULL, 0);
 
 if ( shmptr == (void *) -1)
  {
   printf("shmat 出错了。\n");
   return -1;
  }
 
 pnode = (sq *)shmptr;
 
 
 /* 在共享内存中取数据*/
  printf("到否?\n");
 while(1)
 {
  if(dequeue(pnode,&a)==0)
  {
   printf("从4中取出的数据是:%c\n",a);
  }
 }
 
 
}

      这里主要这个个问题,在B1中如果把printf("从4中取出的数据是:%c\n",a);改成printf("从4中取出

的数据是:%s\n",a);那么在编译的时候也能通过,可是在执行的时候会出现这么一个问题  “段错误”,

为什么呢?一般出现“段错误”,有两个原因:一是内存溢出,二是数组越界。这里的%s,取的时候

是取一串字符串,而在我们的A1中显然是一个字符,一个字符读取,让后存到共享内存,所以在

B1中也应该是一个一个读取。这也说明了一个问题,用文艺点的说法是上下文要一致,即A1,B1

中的所用参数类型应该一致。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值