一.无名管道pipe
特点:
(1)半双工(在同一时刻,数据传输的方向只能是接收或发送);
例如:对于主机和从机而言,在某一时刻,只能是主机发送(从机接收),或者主机接收(从机发送)
(2)只能在具有亲缘关系的进程间使用.进程的亲缘关系一般指的是父子关系
1.pipe()函数原型
在这里插入图片描述返回值为int型,
参数为数组(有2个元素的数组),
成功返回0,失败返回-1,
注意pipefd[0]是读通道,
pipefd[1]是写通道
2.实验:使用pipe()创建两个管道,使用fork创建进程。e父进程向子进程写数据,子进程从父进程读数据。由于pipe是半双工的,所以父进程写数据的时候把都通道关闭,子进程读的时候把写通道关闭。
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{ int fd[2];
int pid;
char *writebuff = "12345\n";
char readbuff[7];
int ret_pipe;
ret_pipe = pipe(fd);
if(ret_pipe == 0)
{
pid = fork();
if(pid < 0)
{
printf("child process creat failed\n");
}
else if(pid > 0)
{
printf("father process creat success\n");
close(fd[0]);
write(fd[1],writebuff,strlen(writebuff));
}
else
{
printf("child process creat success\n");
close(fd[1]);
read(fd[0],readbuff,strlen(readbuff));
printf("readbuff:%s\n",readbuff);
}
}
else
{
printf("creat pipe failed\n");
}
return 0;
}
3.前面的实验父子进程只能通过pipe进行1次通信,接下来将实现父子进程通过pipe持续通信。
pipe读写数据的注意点:““剪切”+“数据长度”+阻塞”
下面的代码是父子进程通过pipe实现持续通信
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
int main()
{ int fd[2];
int pid;
//char *writebuff = "12345\n";
char writebuff[50] = {0};
char readbuff[50]={0};
int ret_pipe;
int parentflag=2;//1-父进程阻塞,2-父进程不阻塞
int childflag=0;//1-子进程阻塞,2-子进程不阻塞
ret_pipe = pipe(fd);
if(ret_pipe == 0)
{
pid = fork();
if(pid < 0)
{
printf("child process creat failed\n");
}
else if(pid > 0)
{
printf("father process creat success\n");
while(1)
{
if(parentflag==1)//如果父进程被阻塞
{
printf("父进程被阻塞\n");
}
else if(parentflag==2)//父进程被解除阻塞
{
childflag=1;//父进程写入之前,子进程被阻塞
scanf("%s",writebuff);
close(fd[0]);
write(fd[1],writebuff,strlen(writebuff)+1);
//childflag=2;//父进程写入成功之后,子进程的阻塞状态被解除
}
else if(parentflag==0)//刚被初始化
{
printf("初始化,请父进程写入数据\n");
parentflag==2;//解除父进程的阻塞状态;
}
}
wait(NULL);//阻塞,直到子进程结束后才执行
printf("father process exit\n");
}
else
{
printf("child process creat success\n");
//利用阻塞,让父进程先进行数据的写入
while(1)
{
if(childflag==1)//如果子进程被阻塞
{
printf("子进程被阻塞\n");
//父进程向pipe写入数据
printf("请父进程向pipe写入数据\n");
childflag=2;
}
else if(childflag==2)//子进程的阻塞被解除
{
parentflag=1;//子进程即将读取数据时,把父进程阻塞
close(fd[1]);
read(fd[0],readbuff,50);//程序会被阻塞在这里,直到管道中有数据
printf("readbuff:%s\n",readbuff);
parentflag=2;//子进程读取结束后,解除对父进程的阻塞
printf("please input dtat\n");
}
else if(childflag==0)//初始化,主动阻塞子进程,让父进程先写入数据
{
childflag=1;
printf("初始化,子进程被阻塞,请父进程写入数据\n");
}
}
}
}
else
{
printf("creat pipe failed\n");
}
return 0;
}
运行结果如下:
在这里插入图片描述