对我来说,这是一个艰难的程序,花了好长时间,才真正完成,对一个初学者
来说,可以学到很多。
进程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
中的所用参数类型应该一致。