目录
一、实现的思路如下图:
因为从有名管道中读取不到数据,read会阻塞,所以需要分别在不同的进程中区读写。 对进程A创建 子进程去读管道数据; 对进程B,创建子进程去写管道数据。
二、代码实现
mychatA.c代码如下:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
int main() {
pid_t pid = fork();
int fdw;
int fdr;
if(pid >0)
{
// 1.判断有名管道文件是否存在
int ret = access("fifo1", F_OK);
if(ret == -1) {
// 文件不存在
printf("管道不存在,创建对应的有名管道\n");
ret = mkfifo("fifo1", 0664);
if(ret == -1) {
perror("mkfifo");
exit(0);
}
}
// 2.以只写的方式打开管道fifo1
fdw = open("fifo1", O_WRONLY);
if(fdw == -1) {
perror("open");
exit(0);
}
printf("打开管道fifo1成功,等待写入...\n");
char buf[128];
// 3.循环的写读数据
while(1) {
memset(buf, 0, sizeof(buf));
// 获取标准输入的数据
fgets(buf, 128, stdin);
// 写数据
ret = write(fdw, buf, strlen(buf));
if(ret == -1) {
perror("write");
exit(0);
}
}
}else if(pid ==0)
{
// 1.判断有名管道文件是否存在
int ret = access("fifo2", F_OK);
if(ret == -1) {
// 文件不存在
printf("管道不存在,创建对应的有名管道\n");
ret = mkfifo("fifo2", 0664);
if(ret == -1) {
perror("mkfifo");
exit(0);
}
}
// 2.以只读的方式打开管道fifo2
fdr = open("fifo2", O_RDONLY);
if(fdr == -1) {
perror("open");
exit(0);
}
printf("打开管道fifo2成功,等待读取...\n");
char buf[128];
// 3.循环的读数据
while(1) {
// 5.读管道数据
memset(buf, 0, sizeof(buf));
int ret = read(fdr, buf, 128);
if(ret <= 0) {
perror("read");
break;
}
printf("Message from B: %s\n", buf);
}
}else{
perror("fork");
exit(0);
}
// 关闭文件描述符
close(fdr);
close(fdw);
return 0;
}
mychatB.c代码如下:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
int main() {
pid_t pid = fork();
int fdw;
int fdr;
if(pid >0)
{
// 1.判断有名管道文件是否存在
int ret = access("fifo1", F_OK);
if(ret == -1) {
// 文件不存在
printf("管道不存在,创建对应的有名管道\n");
ret = mkfifo("fifo1", 0664);
if(ret == -1) {
perror("mkfifo");
exit(0);
}
}
// 2.以只读的方式打开管道fifo1
fdr = open("fifo1", O_RDONLY);
if(fdr == -1) {
perror("open");
exit(0);
}
printf("打开管道fifo1成功,等待读取...\n");
char buf[128];
// 3.循环的读数据
while(1) {
// 读管道数据
memset(buf, 0, sizeof(buf));
ret = read(fdr, buf, 128);
if(ret <= 0) {
perror("read");
break;
}
printf("message from A: %s\n", buf);
}
}else if(pid == 0)
{
// 1.判断有名管道文件是否存在
int ret = access("fifo2", F_OK);
if(ret == -1) {
// 文件不存在
printf("管道不存在,创建对应的有名管道\n");
ret = mkfifo("fifo2", 0664);
if(ret == -1) {
perror("mkfifo");
exit(0);
}
}
// 2.以只写的方式打开管道fifo2
fdw = open("fifo2", O_WRONLY);
if(fdw == -1) {
perror("open");
exit(0);
}
printf("打开管道fifo2成功,等待写入...\n");
char buf[128];
// 3.循环的写数据
while(1) {
memset(buf, 0, sizeof(buf));
// 获取标准输入的数据
fgets(buf, 128, stdin);
// 写数据
int ret = write(fdw, buf, strlen(buf));
if(ret == -1) {
perror("write");
exit(0);
}
}
}else{
perror("fork");
exit(0);
}
// 关闭文件描述符
close(fdr);
close(fdw);
return 0;
}
编译执行:
三、总结
使用有名管道来实现进程间通信,缺点是 对数据的长度是有要求限制的,因为管道的缓冲区大小是固定的。 使用socket套接字就没有这种限制。