- 管道的读写行为
1. 读操作:
a. 有数据可以读
read(fd) -- 正常读取,返回读取的字节数
b. 无数据可以读
(1) 如果读写两端被关闭
read会解除阻塞,返回0。相当是读文件读到了尾部
(2) 如果没有全部关闭
read将阻塞
2. 写操作:
a. 读端被关闭:
(1) 如果管道内被塞满,则管道破裂,进程会被终止
内核将向进程发送SIGPIPE信号,然后终止进程
b. 读端没有被关闭:
(1) 如果缓冲区写满,则write阻塞,等待管道内容被读取后再写入
(2) 如果没有被写满,则write正常写操作
- 查看pipe的缓存区大小
1. 终端命令
ulimit -a
2. 函数
a. 函数原型:
long fpathconf(int fd, int name);
long pathconf(const char* path,int name)
b. 参数:
fd:当使用函数fpathconf时,传入的是文件描述符
path:当使用pathconf时,传入的是文件路径
name:表示要查看的信息,可选有:
_PC_LINK_MAX,_PC_MAX_CANON,_PC_MAX_INPUT,_PC_PATH_MAX,_PC_PIPE_BUF,_PC_CHOWN_RESTRICTED,_PC_NO_TRUNC,_PC_VDISABLE
3. 测试
long size = fpathconf(fd[0], _PC_PIPE_BUF);
printf("size = %ld\n", size); //默认大小为4K,即4096byte
- 设置管道的非阻塞
1. 使用文件操作符修改操作函数fcntl:
a. 先获取原来的信息
int flags = fcntl(fd[0],F_GETFL); //如果修改fd[0]则表示读端非阻塞
b. 添加非阻塞O_NONBLOCK
flags = flags | O_NOBLOCK
fcntl(fd[0], F_SETFL, flags);
- fifo文件:first-in first-out special file
1. 特点:
a. 它是文件系统的一部分
b. 当使用ls -l查看该文件时,其类型为p,即管道。(称为:有名管道)
c. 它是一个伪文件,在磁盘上的大小永远为0
d. 当创建一个fifo文件时,会在内核中开辟一块与之对于缓冲区,用于存储数据
当open一个fifo文件后,会获取一个fd,读写数据时,操作系统完成由fifo文件和内核缓冲区的数据交换
2. 使用场景
适用于没有血缘关系的进程间通信
3. 创建方式:
a. 终端命令
mkfifo
b. 系统函数
int mkfifo(const char *pathname, mode_t mode); //函数创建时,需要提供创建时的权限
4. fifo文件操作
a. open/close:文件开关操作
b. read/write:文件读写操作
不能进行lseek<重置文件指针>操作
5. 进程间通信 -- 类似于操作文件在进程间通信
a. 创建fifo文件 -- myfifo
b. 当前将会有两个进程A(源文件a.c),B(源文件b.c)
c. 若进程A为读操作 -- a.c
int fd_a = open("myfifo",O_RDONLY);
char buf[256];
read(fd_a,buf,sizeof(buf));
close(fd_a);
d. 若进程B为写操作 -- b.c
int fd_b = open("myfifo",O_WRONLY);
write(fd_b,"hello,world",11);
close(fd_b);
6. fifo文件与普通文件在进程间通信的区别
fifo文件为管道,所以读写操作会有阻塞性质。普通文件可能需要在操作读写时使用sleep函数保证不会出现读写交叉。