读了《Unix/Linux系统编程》第三章关于管道部分,根据书上内容与网上资料进行了总结。如果有问题请批评指正!
1. 管道相关概念
管道是用于进程交换数据的单向进程间通信通道。
-
管道有一个读取端进程和一个写入端进程,且读取端进程与写入端进程不能是同一个进程。数据只能从写入端写入,读取端读出。且数据一旦被读走遍不在管道中存在,即不可反复读取。
-
管道不能同时读写,且数据传输方向是单向的。有些系统支持双向管道,数据可以双向传输。
-
读取端读数据时:如果管道上有数据,读进程根据需要读取管道中的数据并返回读取的字节数。如果管道没有数据,但仍有写进程,读进程会等待数据写入。当写进程将数据写入管道后会唤醒等待的读进程,使之读取数据。如果管道既没有数据也没有写进程,读进程返回0。
-
写入端写数据时:会根据需要尽可能多的写入,直到管道写满。如果管道没有空间,但仍有读进程,写进程会等待读进程来腾出空间。当读进程从管道读取数据释放更多空间时会唤醒等待的写进程,让它们继续写入。
需要注意:如果管道不再有读进程,写进程将这种情况视为管道中断错误,终止写入。
-
管道由两个文件描述符fd引用,一个表示读端,一个表示写端
-
可以将管道视为一组相关进程间的有限尺寸FIFO通信信道(通常为4KB)
-
普通管道只能用于相关进程间(如父子进程)通信,命名管道可以用于不相关进程间通信。
2. Unix/Linux中的管道编程
2.1 read系统调用
ssize_t read(int fd, void * buf, size_t count);
第一个参数fd
是文件描述符,第二个参数buf
是缓存区,第三个参数count
是读取字节数。即为从fd代指的文件中读取count个字节到buf缓冲区。
返回读取的字节数,-1表示读取失败,如果在调read之前已到达文件末尾,则这次read返回0。
示例:log.txt文件中有13个字节的内容,main.c文件分三次读取log.txt,每次读取8个字节并打印输出
log.txt
1234567890abc
main.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
int main(){
int fd = open("log.txt",O_RDONLY);//打开文件并返回文件描述符
char buf[20]; //设置缓存区保存读取到的数据
int num = 0; //记录读取到的字节数
num = read(fd,buf,8); //读取8个字节
buf[num] = '\0'; //字符串结尾
printf("%d %s\n",num,buf);
num = read(fd,buf,8); //读取8个字节
buf[num] = '\0'; //字符串结尾
printf("%d %s\n",num,buf);
num = read(fd,buf,8); //读取8个字节
buf[num] =