管道:1.管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;
2.只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);
3.单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统, 并且只存在与内存中;
4.数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据;
5.管道通信是于流式符的;
6.管道的生命周期是随进程的;
7.管道已经给进程提供了同步与互斥;
pipe:
当一个管道建立时,它会创建两个文件描述符pipefd[0]和pipefd[1]。其中pipefd[0]固定用于读管道,而pipefd[1]固定用于写管道,一般文件I/O的函数都可以用来操作管道。
测试pipe的大小
单独创建一个无名管道,并没有实际的意义。我们一般是在一个进程在由pipe()创建管道后,一般再由fork一个子进程,然后通过管道实现父子进程间的通信(因此也不难推出,只要两个进程中存在亲缘关系,这里的亲缘关系指的是具有共同的祖先,都可以采用管道方式来进行通信)。
代码:
结果:
使用管道需要注意以下4中情况:
1.如果所有指向管道写端的文件描述符没关闭,而持有管道写端的进程也没有向管道中写数据,这时有进程从管道读端读数据,那么管道中深剩余的数据都被读取后,再次read
会阻塞,直到管道中有数据可读了才读取数据并返回。
结果:
2.如果所有指向管道写端的文件描述符都关闭了,而仍然有进程从管道的读端读数据,那么管道中深剩余的数据都被读取后,再次read会返回0,就像读到文件末尾一样。
结果:
3.如果所有指向管道读端的文件描述符没关闭,而持有管道读端的进程也没有从管道中读数据,这时有进程从管道写端写数据,那么在管道被写满时再次write会阻塞,直到管道
中有空位置了才写入数据并返回。
4.如果所有指向管道读端的文件描述符都关闭了,这时有进程从管道的写端写数据,那么该进程会收到信号SIGPIPE,通常会导致进程遗产法终止。
结果:
命名管道:FIFO不同于无名管道之处在于它提供了一个路径名与之关联,以FIFO的文件形式存在于文件系统中,这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信,因此,通过FIFO不相关的进程也能交换数据。值的注意的是,FIFO严格遵循先进先出(first in first out),对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。它们不支持诸如lseek()等文件定位操作。
Linux下有两种方式创建命名管道。一是Shell下交互地建立一个命名管道,二是在程序中使用系统函数建立命名管道。Shell方式下可使用mknod或mkfifo命令:
#include<sys/types.h>
#include<sys/stat.h>
int mknod(const char *path,mode_t mod,dev_t dev);
int mkfifo(const char *path,mode_t mode);
函数mknod参数中path为创建的命名管道的全路径名:mod为创建的命名管道的模式,指明其存取权限;dev为设备值,该值取决于文件创建的种类,它只在创建设备文件
时才会用到。这两个函数调用成功都返回0,失败都返回-1.
read:
write:
来源:CSDN
作者:wangiijing
链接:https://blog.csdn.net/wangiijing/article/details/51852587