复制文件描述符
dup函数
作用
复制文件描述符
语法
#include <unistd.h>
int dup(int oldfd);
参数:所需复制的文件描述符
返回值:复制得到的文件描述符
功能:从文件描述符表中,寻找一个最小可能的文件描述符作为oldfd复制
示例1
运行结果
示例2
运行结果
在a.txt文件中打印“啦啦啦”
dup2函数
语法
#include <unistd.h>
int dup2(int oldfd,int newfd);
参数:
oldfd:原有的文件描述符
newfd:指定要复制到的文件描述符,如果该文件描述符已存在,则关闭原有的文件描述符
示例
运行结果
在a.txt中追加了“啦啦啦”
无名管道
概述
无名管道也叫做管道(pipe)
管道是一种特殊类型的文件,在应用层体现为两个打开的文件描述符,一个读fd[0],一个写fd[1]
口诀:0读1写
特点:
1.管道不是普通的文件,不存在于文件系统,只存储在内存中
2.管道是半双工的,数据在同一时刻只能向一个方向流动
单工:数据传输只支持数据向一个方向传输
双工:两台设备之间,允许数据的相互传输
全双工:允许两台设备之间同时进行相互的数据传输(如电话)
半双工:允许两台设备之间进行相互的数据传输,但不允许同时的数据传输,一方 要传送数据,要等另一方传送完成后才行
3.数据只能从管道的一端写入,只能从另一端读出
4.写入管道中的数据遵循先入先出原则
5.管道传输的数据是无格式的,所以读写双方要事先约定好数据的格式,如多少个字节算一个消息
6.管道在内存中对应一个缓冲区,不同系统其大小不同
7.从管道中读取数据是一次性的,一旦数据被取走,就会被管道抛弃,释放资源来存储其他数据
8.管道没有名字,只能在拥有共同祖先的进程中使用
pipe函数
概念
创建管道(无名管道)
语法
#include <unistd.h>
int pipe(fd[2]);
参数:
fd为int型数组的首元素地址,其中fd[0]读,fd[1]写
返回值:
成功:0
失败:1
示例
运行结果
读写特点
1.用read函数从管道中读数据默认是阻塞的
2.用write函数向管道中写数据,当缓冲区已满时,write函数也会阻塞,缓冲区默认大小是64kb
3.通信过程中,当读端口全部关闭后,写进程向管道里写数据时,写进程也会退出(SIGPIPE)
4.编程时可通过fctnl函数设置文件的阻塞特性
阻塞:fcntl(fd, FSETFL,0);
非阻塞:fcntl(fd, FSETFL, O_NONBLOCK);
特点1
运行结果
特点2
缓冲区已满时,write也会阻塞
运行结果
从1到64
特点3
通信过程中,写端关闭,读端会解阻塞
运行结果
五秒后
特点4
通信过程中,若读端关闭,写端会收到SIGPIPE信号退出
运行结果
综合案例
使用代码实现ps -A | grep bash
运行结果
有名管道
概述
有名管道也叫命名管道
特点:
1.半双工,数据在同一时间只能向一个方向流动
2.写入fifo中的数据遵循先入先出原则
3.fifo传输的数据是无格式的,所以读写双方要事先约定好数据的格式,如多少个字节算一个消息
4.fifo在文件系统中作为一个特殊文件而存在,但fifo中的内容却存放在内存中
5.fifo管道在内存中对应一个缓冲区,但不同操作系统的大小不一定相同
6.从fifo中读取的数据是一次性操作,数据一旦被读取,便会被缓冲区释放,以便存储其他数据
7.当使用fifo的进程退出后,fifo文件将继续存储在文件系统中以便后续使用
8.fifo有名字,无血缘关系的进程可以通过打开其命名管道的方式进行通信
mkfifo函数
概念
创建有名管道
语法
读写特点
1、open打开管道 不指定O_NONBLOCK (阻塞)
2、open打开管道 指定O_NONBLOCK (非阻塞)
3、 注意: open 函数以可读可写方式打开 FIFO 文件时的特点:
示例
运行结果
进程以写的方式打开有名管道对应文件,如果此时没有进程以读的方式打开该文件,此时写的进程中的open将会阻塞
给open中移除阻塞
运行结果
1代码
2代码
1
2
1
代码1
代码2
1
2
1
综合案例
代码1
代码2
运行结果