作业一:打开两个终端,要求实现AB进程对话【两根管道】
打开两个终端,要求实现AB进程对话
- A进程先发送一句话给B进程,B进程接收后打印
- B进程再回复一句话给A进程,A进程接收后打印
- 重复1.2步骤,当收到quit后,要结束AB进程
- 提示:两根管道
A终端代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
/***************************A终端***************************/
int main(int argc, const char *argv[])
{
//创建管道1 A终端写入--->管道1--->B终端读取
if(mkfifo("./fifo",0664) < 0)
{
if(errno != 17)//如果错误是已有管道,则跳过,可正常运行
{
perror("mkfifo");
return -1;
}
}
printf("mkfifo pipe1 success __%d__\n",__LINE__);
//创建管道2 B终端写入--->管道2--->A终端读取
if(mkfifo("./myfifo",0664) < 0)
{
if(errno != 17)
{
perror("mkfifo");
return -1;
}
}
printf("mkfifo pipe2 success __%d__\n",__LINE__);
//以写的方式打开管道1
int fd_w=open("./fifo",O_WRONLY);
if(fd_w < 0)
{
perror("open");
return -1;
}
printf("open pipeA success __%d__\n",__LINE__);
//以读的方式打开管道B
int fd_r=open("./myfifo",O_RDONLY);
if(fd_r < 0)
{
perror("open");
return -1;
}
printf("open pipeB success __%d__\n",__LINE__);
char buf[128]="";
ssize_t res = 0;
int c=-1;
while(1)
{
//管道1操作(写入数据)
printf("请输入要对B说的话>>> ");
fgets(buf,sizeof(buf),stdin); //从终端获取数据
buf[strlen(buf)-1] = '\0'; //将\n改成\0
if((write(fd_w,buf,sizeof(buf))) < 0) //将字符串写进管道A
{
perror("write");
return -1;
}
//当管道1的读段关闭,管道1的写段尝试写入数据,则管道破裂,退出进程
//管道2操作(读取数据)
bzero(buf,sizeof(buf));//清空字符串
res=read(fd_r,buf,sizeof(buf));//读取B管道中的数据
c=strcmp(buf,"quit");//将读到的数据与quit比较
if(0 == c)//如果相同,c为0,达到退出条件,可以退出循环
{
break;
}
//printf("写入数据成功 res=%ld\n",res);
if(res < 0)//read函数执行失败,返回负数
{
perror("read");
return -1;
}
if(0 == res)//read执行成功,但读到了0个数据`
{
printf("对方进程退出\n");
break;
}
//打印从管道2中读取到的数据
printf("B:%s\n",buf);
}
//关闭管道1、管道2
close(fd_r);
close(fd_w);
return 0;
}
B终端代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
/***************************B终端***************************/
int main(int argc, const char *argv[])
{
//创建管道1 A终端写入--->管道1--->B终端读取
if(mkfifo("./fifo",0664) < 0)
{
if(errno != 17)
{
perror("mkfifo");
return -1;
}
}
printf("mkfifo pipe1 success __%d__\n",__LINE__);
//创建管道2 B终端写入--->管道2--->A终端读取
if(mkfifo("./myfifo",0664) < 0)
{
if(errno != 17)
{
perror("mkfifo");
return -1;
}
}
printf("mkfifo pipe2 success __%d__\n",__LINE__);
//以读的方式打开管道1
int fd_r=open("./fifo",O_RDONLY);
if(fd_r < 0)
{
perror("open");
return -1;
}
printf("open pipe1 success __%d__\n",__LINE__);
//以写的方式打开管道2
int fd_w=open("./myfifo",O_WRONLY);
if(fd_w < 0)
{
perror("open");
return -1;
}
printf("open pipe2 success __%d__\n",__LINE__);
char buf[128]="";
ssize_t res = 0;
int c=-1;
while(1)
{
//管道1操作(读取数据)
bzero(buf,sizeof(buf));
res=read(fd_r,buf,sizeof(buf));
c=strcmp(buf,"quit");//判断B终端输入的是否是quit
if(0 == c)
{
break;//是quit则退出进程
}
if(res < 0)
{
perror("read");
return -1;
}
if(0 == res )
{
printf("对方进程退出\n");
break;
}
printf("A:%s\n",buf);
//管道2操作(写入数据)
printf("请输入>>> ");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = '\0';
if((write(fd_w,buf,sizeof(buf))) < 0)
{
perror("write");
return -1;
}
//当管道2关闭,管道2的写段尝试写入数据,则管道破裂,退出进程
}
close(fd_r);
close(fd_w);
return 0;
}
A终端结果
ubuntu@ubuntu:02_fifo$ gcc 03_pipe_w.c -o w
ubuntu@ubuntu:02_fifo$ ./w
mkfifo pipe1 success __22__
mkfifo pipe2 success __33__
open pipeA success __42__
open pipeB success __50__
请输入要对B说的话>>> 你好,我是A
B:你好呀,我是B
请输入要对B说的话>>> 你吃饭了吗?
B:吃了,你呢
请输入要对B说的话>>> 不告诉你
ubuntu@ubuntu:02_fifo$
B终端结果
ubuntu@ubuntu:02_fifo$ gcc 02_pipe_r.c -o r
ubuntu@ubuntu:02_fifo$ ./r
mkfifo pipe1 success __22__
mkfifo pipe2 success __33__
open pipe1 success __42__
open pipe2 success __50__
A:你好,我是A
请输入>>> 你好呀,我是B
A:你吃饭了吗?
请输入>>> 吃了,你呢
A:不告诉你
请输入>>> quit
对方进程退出
ubuntu@ubuntu:02_fifo$
作业二:在作业一的基础上,AB能随时发信息给对方(全双工)
此代码需要双方终端都输入quit才能结束对话
A终端代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>
/***************************A终端***************************/
int main(int argc, const char *argv[])
{
umask(0);
//创建管道1(发送) A终端写入--->管道1--->B终端读取
if(mkfifo("./fifo",0777) < 0)
{
if(errno != 17)//如果错误是已有管道,则跳过,可正常运行
{
perror("mkfifo");
return -1;
}
}
printf("mkfifo pipe1 success __%d__\n",__LINE__);
umask(0);
//创建管道2(接收) B终端写入--->管道2--->A终端读取
if(mkfifo("./myfifo",0664) < 0)
{
if(errno != 17)
{
perror("mkfifo");
return -1;
}
}
printf("mkfifo pipe2 success __%d__\n",__LINE__);
//创建子进程
pid_t cpid=fork();
//以写的方式打开管道1
int fd_w=open("./fifo",O_WRONLY);
if(fd_w < 0)
{
perror("open");
return -1;
}
printf("open pipeA success __%d__\n",__LINE__);
//以读的方式打开管道B
int fd_r=open("./myfifo",O_RDONLY);
if(fd_r < 0)
{
perror("open");
return -1;
}
printf("open pipeB success __%d__\n",__LINE__);
char buf[128]="";
ssize_t res = 0;
int c=-1;
if(0 == cpid)//子进程发送 fifo
{
while(1)
{
//管道1操作(写入数据)
fgets(buf,sizeof(buf),stdin); //从终端获取数据
buf[strlen(buf)-1] = '\0'; //将\n改成\0
if((write(fd_w,buf,sizeof(buf))) < 0) //将字符串写进管道A
{
perror("write");
return -1;
}
//当管道1的读段关闭,管道1的写段尝试写入数据,则管道破裂,退出进程
if(strcmp(buf,"quit") == 0)//如果相同,c为0,达到退出条件,可以退出循环
{
break;
}
//printf("写入数据成功 res=%ld\n",res);
}
close(fd_w);
_exit(0);
}
else if(cpid > 0)//父进程接收 myfifo
{
while(1)
{
//管道2操作(读取数据)
bzero(buf,sizeof(buf));//清空字符串
res=read(fd_r,buf,sizeof(buf));//读取B管道中的数据
if(res < 0)//read函数执行失败,返回负数
{
perror("read");
return -1;
}
if(0 == res)//read执行成功,但读到了0个数据`
{
break;
}
if(strcmp(buf,"quit")==0)
break;
//打印从管道2中读取到的数据
printf("B:%s\n",buf);
}
wait(NULL);
close(fd_r);
}
//关闭管道1、管道2
close(fd_r);
close(fd_w);
return 0;
}
B终端代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>
/***************************B终端***************************/
int main(int argc, const char *argv[])
{
//创建管道1(接收) A终端写入--->管道1--->B终端读取
if(mkfifo("./fifo",0777) < 0)
{
if(errno != 17)
{
perror("mkfifo");
return -1;
}
}
printf("mkfifo pipe1 success __%d__\n",__LINE__);
//创建管道2(发送) B终端写入--->管道2--->A终端读取
if(mkfifo("./myfifo",0777) < 0)
{
if(errno != 17)
{
perror("mkfifo");
return -1;
}
}
printf("mkfifo pipe2 success __%d__\n",__LINE__);
//创建子进程
pid_t cpid=fork();
//以读的方式打开管道1
int fd_r=open("./fifo",O_RDONLY);
if(fd_r < 0)
{
perror("open");
return -1;
}
printf("open pipe1 success __%d__\n",__LINE__);
//以写的方式打开管道2
int fd_w=open("./myfifo",O_WRONLY);
if(fd_w < 0)
{
perror("open");
return -1;
}
printf("open pipe2 success __%d__\n",__LINE__);
char buf[128]="";
ssize_t res = 0;
//int c=-1;
if(0 == cpid)//子进程接收 fifo
{
while(1)
{
//管道1操作(读取数据)
bzero(buf,sizeof(buf));
res=read(fd_r,buf,sizeof(buf));
if(res < 0)
{
perror("read");
return -1;
}
if(0 == res )
{
break;
}
if(strcmp(buf,"quit")==0)
break;
printf("A:%s\n",buf);
}
close(fd_r);
_exit(0);
}
else if(cpid > 0)//父进程发送 myfifo
{
while(1)
{
//管道2操作(写入数据)
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] = '\0';
if((write(fd_w,buf,sizeof(buf))) < 0)
{
perror("write");
return -1;
}
//当管道2关闭,管道2的写段尝试写入数据,则管道破裂,退出进程
if(strcmp(buf,"quit") == 0)//判断B终端输入的是否是quit
{
break;
}
}
close(fd_w);
wait(NULL);
}
else
{
perror("fork");
return -1;
}
close(fd_r);
close(fd_w);
return 0;
}