消息队列(message queue)
Quesion1
1)要求AB进程做通信
-
A进程发送一句话,B进程接收打印
-
然后B进程发送给A进程一句话,A进程接收打印
在基础上实现,AB进程能够随时收发数据
代码实现
A进程
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include<string.h>
#include <signal.h>
#include <unistd.h>
#define TYPE 1
#define TYPE2 2
struct msgbuf
{
long mtype;
char mtext[128];
};
int main(int argc,const char *argv[])
{
//计算key值
key_t key = ftok("./", 1);
if(key < 0)
{
perror("ftok" );
return -1;
}
printf("key=%#x\n",key);
//创建一个消息队列
int msqid = msgget(key, IPC_CREAT|0664);
if(msqid < 0)
{
perror("msgget");
return - 1;
}
printf("msqid=%d\n", msqid);
//发送消息包
pid_t pid;
struct msgbuf snd;
struct msgbuf rcv;
ssize_t res =0;
pid=fork();
if(pid>0)
{
while(1)
{
// printf("输入消息类型>>>");//手动获取消息类型
// scanf("%ld",&snd.mtype);
// getchar();
snd.mtype=TYPE;//消息类型
// strcpy(snd.mtext,"1");
printf("请输入>>>");
fgets(snd.mtext,sizeof(snd.mtext),stdin);
snd.mtext[strlen(snd.mtext)-1] = 0;
//阻塞方式发送,消息队列满了,阻塞
if(msgsnd(msqid,&snd,sizeof(snd.mtext),0)<0)
{
perror("msgsnd");
return -1;
}
printf("消息包发送成功\n");
if(strcmp(snd.mtext,"quit")==0)
{
kill(pid,2);
exit(0);
}
}
}
if(pid==0)
{
while(1)
{
res=msgrcv(msqid,&rcv,sizeof(rcv.mtext),TYPE2,0);
if(res<0)
{
perror("msgrcv");
return-1;
}
printf("res=%ld [%ld :%s]\n",res,rcv.mtype,rcv.mtext);
if(strcmp(rcv.mtext,"quit")==0)
{
printf("接受到退出指令");
kill(getppid(),2);
exit(0);
}
}
}
system("ipcs -q");
return 0;
}
B进程
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include<string.h>
#include <signal.h>
#include <unistd.h>
#define TYPE 1
#define TYPE2 2
struct msgbuf
{
long mtype;
char mtext[128];
};
int main(int argc,const char *argv[])
{
//计算key值
key_t key = ftok("./", 1);
if(key < 0)
{
perror("ftok" );
return -1;
}
printf("key=%#x\n",key);
//创建一个消息队列
int msqid = msgget(key, IPC_CREAT|0664);
if(msqid < 0)
{
perror("msgget");
return - 1;
}
printf("msqid=%d\n", msqid);
//发送消息包
pid_t pid;
struct msgbuf snd;
struct msgbuf rcv;
ssize_t res =0;
pid=fork();
if(pid>0)
{
while(1)
{
//printf("输入消息类型>>>");//手动获取消息类型
//scanf("%ld",&snd.mtype);
//getchar();
snd.mtype=TYPE2;//消息类型
// strcpy(snd.mtext,"1");
printf("请输入>>>");
fgets(snd.mtext,sizeof(snd.mtext),stdin);
snd.mtext[strlen(snd.mtext)-1] = 0;
//阻塞方式发送,消息队列满了,阻塞
if(msgsnd(msqid,&snd,sizeof(snd.mtext),0)<0)
{
perror("msgsnd");
return -1;
}
printf("消息包发送成功\n");
if(strcmp(snd.mtext,"quit")==0)
{
kill(pid,2);
exit(0);
}
}
}
if(pid==0)
{
while(1)
{
res=msgrcv(msqid,&rcv,sizeof(snd.mtext),TYPE,0);
if(res<0)
{
perror("msgrcv");
return-1;
}
printf("res=%ld [%ld :%s]\n",res,rcv.mtype,rcv.mtext);
if(strcmp(rcv.mtext,"quit")==0)
{
printf("接受到退出指令");
kill(getppid(),2);
exit(0);
}
}
}
system("ipcs -q");
return 0;
}
运行现象
共享内存(shared memory)
Question2
- A进程写入一个整型,在该整型后,写入一个字符串
- B进程将共享内存中的整型以及字符串读取出来;
代码实现
输入程序
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<stdlib.h>
#include<string.h>
#include<sys/shm.h>
//a进程
int main(int argc, const char *argv[])
{
//创建共享文件
key_t key =ftok("./",1);
if(key<0)
{
perror("ftok");
return -1;
}
//创建共享内存
int shmid=shmget(key,100,IPC_CREAT|0777);//在key值空间创建一个大小为100字节的共享空间,如果不存在,则创建,其权限为0777
if(shmid<0)
{
perror("shmget");
return -1;
}
printf("shmid =%d\n",shmid);
//共享内存的映射
void *shmaddr=shmat(shmid,NULL,0);
//写入
int wr_in;
int *p=(int*)shmaddr;//用整形指针变量P接收共享内存的首地址
printf("输入需要写入的整形数据>>>");
scanf("%d",wr_in);
getchar();//回收垃圾字符
*p=12233;//由于P是整形指针变量,可以直接向其所指向的地址空间写入整形数据
char str[100];
char *q=(char*)(p+1);//用字符型指针变量q接收存储整形变量后空余地址空间的首地址
scanf("%s",str);
strcpy(q,str);//向q指向地址空间中写入字符串
system("ipcs -m");
return 0;
}
输出程序
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<sys/shm.h>
//b进程
int main(int argc, const char *argv[])
{
//创建共享文件
key_t key =ftok("./",5);
if(key<0)
{
perror("ftok");
return -1;
}
//创建共享内存
int shmid=shmget(key,32,IPC_CREAT|0777);
if(shmid<0)
{
perror("shmget");
return -1;
}
printf("shmid =%d\n",shmid);
//共享内存的映射
void *shmaddr=shmat(shmid,NULL,0);
//读出
int *p=(int*)shmaddr;//用整形指针变量P接收共享内存的首地址
printf("%d\n",*p);
char *q=(char*)(p+1);//用字符型指针变量q接收存储整形变量后空余地址空间的首地址
printf("%s\n",q);//以字符串形式打出指针变量q指向地址往后所存入的连续字符变量
system("ipcs -m");
return 0;
}