一、代码
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define len 30
#define MAC 7L
// 结构体,用于传输文件
struct msgbuf
{
long mtype;
char mtext[len]; // 真正存放数据的地址
}msg_pos,msg_tos;
int main()
{
/*---------创建消息对列--------*/
// 创建keyIPC_MASK
key_t key = ftok("./",1);
if (key == -1)
{
perror("ftok failed");
return 2;
}
// 创建一个消息对列
int msg_id = msgget(key,IPC_CREAT|0666);
if (msg_id == -1)
{
perror("msgget failed");
return 3;
}
/*+++++++++ 准备工作 +++++++++++*/
// 打开文件,读出数据
// 打开将要读取的文件
FILE *fp = fopen("1.txt","r");
if (fp == NULL)
{
perror("fopen failed");
exit(-1);
}
// 打开将要写入的文件
FILE *fp2 = fopen("2.txt","w+");
if (fp2 == NULL)
{
perror("fopen failed");
exit(-1);
}
memset(&msg_pos,0,sizeof(msg_pos)); // 清空
memset(&msg_tos,0,sizeof(msg_tos));
msg_pos.mtype = MAC; // 设置消息的标识为7L
while (1)
{
/*----------- 读出数据并发送,直到数据结束 -----------*/
memset(msg_pos.mtext,0,len);
memset(msg_tos.mtext,0,len); // 清空原来的数据
int ret = fscanf(fp,"%s ",msg_pos.mtext);
if (ret == EOF)
break;
// 将数据通过消息对列写入另外的文件中去
int msg_ret = msgsnd(msg_id,&msg_pos,strlen(msg_pos.mtext),0);
if (msg_ret == -1)
{
perror("msgsnd failed");
exit(-1);
}
/*----------- 接受数据并写入文件,直到数据结束 -----------*/
int grcv_ret = msgrcv(msg_id,&msg_tos,len,MAC,0);
if (grcv_ret == -1)
{
perror("msgrcv failed");
exit(-1);
}
// 把temp中的数据写入到文件中
fprintf(fp2,"%s ",msg_tos.mtext);
}
int msgctl_ret_b = msgctl(msg_id,IPC_RMID,NULL);
if(msgctl_ret_b == -1)
{
perror("msgctl");
return -1;
}
fclose(fp);
fclose(fp2);
return 0;
}
二、效果
三、总结
1. 特别注意的是 结构体的长度
2. 在创建消息对列时,使用的msgget函数的第二个参数是:IPC_CREAT|0666
3. 在使用fopen时,要注意文件的打开方式,“r”“w”“a”“w+”.....
4. 每一个函数的返回值是不一样的,msgget、msgsnd、msgrcv、msgctl 是 int 型;而文件io里的函数返回值则各不相同。fscanf(对文件读取)、fprintf(写入文件中)的返回值也是int 型,fopen的返回值是FILE类型的指针。
5. 在每一次的循环中,都要对结构体中的数据清零,但是不能清除整个结构体,因为里面包含了用于消息对列传输的消息标识(mtype)
6. 在最后要关闭文件,且要杀死消息对列
谢谢观看!