管道限制
管道写入数据,读端没有读到原因:
一个管道的容量是有限的。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,即部分写入,写入时可能有其他进程穿插写入。
POSIX规定,少于 PIPE_BUF 的写操作必须原子完成,如果此时管道空闲缓冲区不足以容纳要写入的字节数,则进入睡眠,直到当缓冲区中能够容纳要写入的字节数时,才开始进行一次性写操作。
通过ulimit -a命令查看得知pipesize一项返回是8,单位是512bytes,也就是4K。获得的数据小于PIPE_BUF(在Linux上,PIPE_BUF为4096字节),管道空闲缓冲区进入等待。管道写端关闭,同时将数据写入空闲缓冲区,同时管道读端读取空闲缓冲区中的数据并获得管道写段关闭的信号,从而管道读端关闭。
解决办法:
修改管道限制大小:
//Linux上,可能不介意不可移植性,你可能对文件描述符操纵器F_SETPIPE_SZ感兴趣,这可以从Linux 2.6.35开始.
int pipe_sz = fcntl(pipe_des[1],F_SETPIPE_SZ,sizeof(size_t));
在调用之后会发现pipe_sz =getpagesize(),因为缓冲区不能小于系统页面大小.见man,fcntl(2).
如果当前linux版本没有到 2.6.35可以查看 2.6.35版本的源码,尝试补丁或者将将版本切换到linux 2.6.35