http://blog.csdn.net/lne818/article/details/1005052
管道不支持文件定位操作
管道
- 父子进程或兄弟进程间的通信
- 数据只能单向流动,要求双向通信时需建立两条管道
- 通过建立于内存中的文件实现
管道的使用
- int fd[2]; int pipe(fd); (#include <unistd.h>) 相当于同时open两个文件描述符
- 其中 fd[0] 用于读 fd[1]用于写,通过缓存PIPE_BUF连接
- PIPE_BUF满时,写端阻塞;PIPE_BUF空时,读段返回0
- 写端关闭后,写入的数据仍存在,直到读出为止
- 读端关闭后(各亲缘进程中读端均关闭),写入的数据会使本进程收到内核传来的SIGPIPE信号,默认终止进程
- linux不保证写操作的原子性,一次write操作可能被分多次写入PIPE_BUF
有名管道
- 对管道的改进,无名管道通信用的文件描述符必须通过进程的亲缘关系传递。
- 有名管道使得通信用的文件描述符可通过管道名获得,故支持任意进程间的通信
有名管道的使用
- int mkfifo(const char * pathname, mode_t mode) (#include <sys/types.h> #include <sys/stat.h>)
- pathname为文件系统中存在的文件时,返回ENXIO错误
- 如果有进程写打开FIFO,且当前FIFO内没有数据,则对于设置了阻塞标志的读操作来说,将一直阻塞。对于没有设置阻塞标志读操作来说则返回-1,当前errno值为EAGAIN,提醒以后再试。
- 对于设置了阻塞标志的读操作说,造成阻塞的原因有两种:当前FIFO内有数据,但有其它进程在读这些数据;另外就是FIFO内没有数据。解阻塞的原因则是FIFO中有新的数据写入,不论信写入数据量的大小,也不论读操作请求多少数据量。
- 读打开的阻塞标志只对本进程第一个读操作施加作用,如果本进程内有多个读操作序列,则在第一个读操作被唤醒并完成读操作后,其它将要执行的读操作将不再阻塞,即使在执行读操作时,FIFO中没有数据也一样(此时,读操作返回0)。
- 如果没有进程写打开FIFO,则设置了阻塞标志的读操作会阻塞。
- 对于设置了阻塞标志的写操作:
当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。如果此时管道空闲缓冲区不足以容纳要写入的字节数,则进入睡眠,直到当缓冲区中能够容纳要写入的字节数时,才开始进行一次性写操作。当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。FIFO缓冲区一有空闲区域,写进程就会试图向管道写入数据,写操作在写完所有请求写的数据后返回。
- 对于没有设置阻塞标志的写操作:
当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。在写满所有FIFO空闲缓冲区后,写操作返回。当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。如果当前FIFO空闲缓冲区能够容纳请求写入的字节数,写完后成功返回;如果当前FIFO空闲缓冲区不能够容纳请求写入的字节数,则返回EAGAIN错误,提醒以后再写;