我听说对于命名管道,小于 512 字节的写入是原子的(写入不会交错)。
有没有办法增加特定命名管道的数量?
就像是:
mkfifo mynamedpipe --buf=2500
据说这是完整的文档: http://www.gnu.org/software/coreutils/manual/html_node/mkfifo-invocable.html#mkfifo-inspiration
man mkfifo
带我到那个页面。
答案1
文件fifo
只是一种文件类型,当打开它进行读取和写入时,会像 pipeline() 系统调用一样实例化管道。
至少在 Linux 上,通过该管道传输的数据根本不存储在文件系统上(仅作为内核内存存储在内核中)。还有尺寸fifo 文件的属性不相关并且始终为 0。
在 Linux 上,您可以使用 更改管道缓冲区的大小(无论该管道是使用实例化pipe()
还是通过打开 fifo 文件实例化)F_SETPIPE_SZ
fcntl()
,但对于非特权用户,它受 约束/proc/sys/fs/pipe-max-size
。管道的任何编写者或读者都可以发出该命令,fcntl()
尽管对编写者来说这样做更有意义。对于命名管道,您需要对通过 fifo 文件实例化的每个管道执行此操作。
$ mkfifo fifo
$ exec 3<> fifo # instantiate the pipe
$ seq 20000 > fifo
^C # seq hangs because it's trying to write more than 64KiB
$ exec 3<&- 3<> fifo # close the first pipe and instantiate a new one
$ (perl -MFcntl -e 'fcntl(STDOUT, 1031, 1048576)'; seq 20000) > fifo
$ # went through this time
上面,我曾经perl
发出过fcntl()
,对(我的系统上的 1031)的值进行编码F_SETPIPE_SZ
。
答案2
不是改变,而是有一个具有相同效果的 bash shell 实现,通过替换 processus 来F_SETPIPE_SZ
替换表达式,如下所示:(它将在运行时被文件描述符替换)fifo
>(stdbuf -o100M grep -a '^' > fifo)
/dev/fd/63
mkfifo fifo
exec 3<> fifo
seq 12000000 > >(stdbuf -o100M grep -a '^' > fifo)
并非所有过滤器都对通过 改变缓冲模式敏感stdbuf
,您不能简单地使用cat
例如。出于同样的原因,你也不能说stdbuf -o100M seq 12000000 > fifo
。据我所知,经典sed
grep
还是awk
做吧。
这样做的缺点是需要多启动一个进程;优点是您可以自由地实现巨大的缓冲区大小。