Linux管道使用注意事项和经验
如何保证写入原子性
一个管道的容量是有限的。POSIX规定,少于 PIPE_BUF的写操作必须原子完成:要写的数据应被连续的写到管道;大于 PIPE_BUF 的写操作可能是非原子的: 内核可能会把此数据与其它进程的对此管道的写操作交替起来。POSIX规定PIPE_BUF至少为512B(linux中为4096B),具体的语义如下: 其中n为要写的字节数
n <= PIPE_BUF, O_NONBLOCK无效:原子的写入n个字节。如果管道当前的剩余空间不足以立即写入n个字节,就阻塞直到有足够的空间。
n <= PIPE_BUF, O_NONBLOCK有效:写入具有原子性,如果有足够的空间写入n个字节,write立即成功返回。否则一个都不写入,返回错误,并设置errno为EAGAIN。
n > PIPE_BUF, O_NONBLOCK无效:非原子写。可能会和其它的写进程交替写。write阻塞直到将n个字节写入管道。
n > PIPE_BUF, O_NONBLOCK有效:如果管道满,则write失败,返回错误,并将errno设置为 EAGIN。如果不满,则返回写入的字节数为1~n,即部分写入,写入时可能有其他进程穿插写入。
结论:
1、当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。
2、当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性
PIPE_BUF 缓冲区 4096字节
PIPE 总容量 65536字节 = PIPE_BUF * 16 这些都是Linux硬编码定义的
成功创建命名管道文件的前提
1.文件所在目录不能是FAT32,FAT32不支持mknod(mkfifo会调用mknod)
2.要有目录的文件读写权限
3.如果系统开启selinux,要保证有selinux权限
管道文件注意事项
1.如果所有读取端描述符都已关闭,此时进程再次往管道里面写入数据,写操作会失败,errno被设置为EPIPE,同时内核会向写入进程发送一个SIGPIPE的信号
2.当所有的读取端和写入端都关闭后,管道才能被销毁
3.只有当所有的写入端描述符都已关闭,且管道中的数据都被读出,对读取端描述符调用read函数才会返回0(即读到EOF标志)
3、若管道文件没有被以写的方式打开,则以只读打开会阻塞
4、若管道文件没有被以读的方式打开,则以只写打开会阻塞