无名管道:
1)只能用于具有亲缘关系的进程之间的通信(无名管道是某一个进程创建的,不像普通文件有路径,在文件系统中是不可见的,其他进程要想打开,只能通过继承的方式去打开)
2)半双工的通信模式,具有固定的读端和写端
3)管道可以看成是一种特殊的文件,对于它的读写可以使用文件IO如read、write函数。
4)管道是基于文件描述符的通信方式。当一个管道建立时,它会创建两个文件描述符fd[0]和fd[1]。其中fd[0]固定用于读管道,而fd[1]固定用于写管道。
注意事项:
1)当管道中无数据时,读操作会阻塞
2)管道中有数据,将写端关闭,可以将数据读出
3)管道中无数据,将写端关闭,读操作会立即返回
4)管道中装满数据写阻塞,一旦有4k空间,写继续
5)只有在管道的读端存在时,向管道中写入数据才有意义。否则,会导致管道破裂,向管道中写入数据的进程将收到内核传来的SIGPIPE信号(通常Broken pipe错误)。
6)不管pipe还是FIFO当把读端和写端都关闭的时候,管道存放在内存中的内容都会被自动释放
7)当用open打开的时候,当只打开读端,或者只打开写端,open会阻塞
创建无名管道:
int pipe(int pipefd[2]);
参数:文件描述符 fd[0]:读端 fd[1]:写端
成功返回 0 ,失败返回 -1
例子1:管道中没有数据时读操作阻塞
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
int fd[];
char buf[] = {};//缓存 if(pipe(fd)!=)// 创建无名管道
{
perror("pipe fail: ");
exit();
}
printf("%d %d\n",fd[],fd[]);//打开的文件描述符,此处为3,4 默认打开 0,1,2,标准输入,输出,出错
//管道中没有数据的时候读阻塞
// write(fd[],"hello",); //此处不向管道写数据时,读操作会阻塞,管道中有数据时,读操作后结束进程
read(fd[],buf,);
printf("%s",buf);
putchar(); // '\n'
return ;
}
测试:读操作一直阻塞
例子2:管道中有数据,将写端关闭,可以将数据读出
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
int fd[];
char buf[] = {};//缓存
if(pipe(fd)!=)// 创建无名管道
{
perror("pipe fail: ");
exit();
}
printf("%d %d\n",fd[],fd[]);//打开的文件描述符,默认打开 0,1,2
//管道中有数据,写端关闭,可以将数据读出
write(fd[],"",); //向管道中写入数据,然后关闭写端
close(fd[]);
read(fd[],buf,);
printf("%s",buf);
putchar(); // '\n'
return ;
}
测试:
例子3:管道中无数据,将写端关闭,读操作会立即返回
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
int fd[];
char buf[] = {};//缓存
if(pipe(fd)!=)// 创建无名管道
{
perror("pipe fail: ");
exit();
}
printf("%d %d\n",fd[],fd[]);//打开的文件描述符,默认打开 0,1,2
//写端关闭,管道中无数据,读操作立即返回
close(fd[]);
read(fd[],buf,); return ;
}
测试:管道中无数据,写端关闭,读操作直接返回
例子4:管道大小 64K
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> int main(int argc, const char *argv[])
{
int fd[];
char buf[] = {};//缓存
if(pipe(fd)!=)// 创建无名管道
{
perror("pipe fail: ");
exit();
}
printf("%d %d\n",fd[],fd[]);//打开的文件描述符,默认打开 0,1,2
//管道大小 64k
int num = ;
ssize_t size;
while() //循环一直运行,当写入 64K 后悔阻塞
{
size = write(fd[],"",);
printf("size = %ld\n",size); //每次写入1024个字节,即 1K ,此次编译会警告
num++;
printf("num = %d\n",num);
}
return ;
}
测试:
警告类型不匹配
例子5: 管道中装满数据写阻塞,一旦有4k空间,写继续
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> //int pipe(int pipefd[2]); int main(int argc, const char *argv[])
{
int fd[]; char buf_w[] = {}; //一次写入 64K 数据
char buf_r[] = {}; //一次读出 4K 数据 if(pipe(fd)!=)// 创建无名管道
{
perror("pipe fail: ");
exit();
} printf("%d %d\n",fd[],fd[]);//打开的文件描述符,默认打开 0,1,2 //管道中装满数据写阻塞,一旦有 4k, 才可以继续进行写操作
write(fd[],buf_w,);//一次写入 64k
// read(fd[0],buf_r,4096); //一次读出4k,在进行写操作 ,程序直接结束
read(fd[],buf_r,); //一次读出 4k-1,在进行写操作 ,此时运行程序阻塞
write(fd[],"a",); // 先读出 4K 数据在写一个字符,或者读4K - 1 个字符,在进行写操作 return ;
}
测试:当读出 4K 数据时可以正常写入,当读出 4K-1 数据时 程序阻塞