Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 为什么pipe.write会阻塞线程?_Ruby - Fatal编程技术网

Ruby 为什么pipe.write会阻塞线程?

Ruby 为什么pipe.write会阻塞线程?,ruby,Ruby,以下是示例程序: from = File.open('test.bin', 'rb') to = IO.popen('cat', 'w+b') i = 0 while buff = from.read(4096) to.write(buff) # blocks here i += 1 print "#{i}, #{buff.size} bytes read \r" end 它读取二进制文件(您可以在Linux上使用fallocate-l 1MB te

以下是示例程序:

from = File.open('test.bin', 'rb')
to = IO.popen('cat', 'w+b')
i = 0

while buff = from.read(4096)
  to.write(buff) # blocks here
  i += 1
  print "#{i}, #{buff.size} bytes read                \r"
end
它读取二进制文件(您可以在Linux上使用
fallocate-l 1MB test.bin创建它),并将管道传输到
cat
命令

但是,
to.write(buff)
调用挂起。以下是它在控制台中的外观:

[1] pry(main)> from = File.open('test.bin', 'rb')
#<File:test.bin>
-rw-rw-r-- 1 admin admin 1000000 Mar 30 13:38 test.bin
[2] pry(main)> to = IO.popen('cat', 'w+b')
#<IO:fd 14>
[3] pry(main)> i = 0
0
[4] pry(main)> 
[5] pry(main)> while buff = from.read(4096)
[5] pry(main)*   to.write(buff)  
[5] pry(main)*   i += 1  
[5] pry(main)*   print "#{i}, #{buff.size} bytes read                \r"  
[5] pry(main)* end  
33, 4096 bytes read                
[1]pry(main)>from=File.open('test.bin','rb')
#
-rw-rw-r--1管理员1000000 3月30日13:38 test.bin
[2] 撬(主)>至=IO.popen('cat','w+b')
#
[3] 撬(主)>i=0
0
[4] 撬动(主)>
[5] 撬动(主)>而缓冲=从读取(4096)
[5] 撬动(主)*写入(buff)
[5] 撬(主)*i+=1
[5] pry(主)*打印“#{i},#{buff.size}字节读取\r”
[5] 撬(主)*端
读取334096字节
所以它只写135168字节。但是为什么呢

此外,如果我使用不同的命令(我需要它用于带有一些参数的gpg),字节数是不同的(大约60 MB),但结果是相同的,它在完全相同的点阻塞(这一点对于
cat
gpg
是不同的,对于每个程序来说,无论您运行程序多少次,它都是相同的)


环境:UbuntuLinux,ruby 2.3.4p301

它之所以会阻塞,是因为
IO.popen
打开了一个包含写入和读取文件句柄以及相关读写缓冲区的管道

由于您根本没有从
io
对象的读取句柄读取数据,因此读取缓冲区最终会满(因为
cat
不断地将其输入复制到输出),并且一旦读取缓冲区满了,操作系统就会阻塞管道的写入端,直到读取缓冲区中再次出现空间

你实际上造成了僵局

解决方案是保持从读取端读取,以防止读取缓冲区阻塞,或者不使命令输出任何内容

从读取句柄读取可能很棘手,因为它本身就是一个阻塞调用。您需要设置非阻塞读取,或者您可以使用单独的线程来执行读取

但是,最简单的解决方案是防止
cat
输出任何内容,因此永远不会造成死锁情况:

to = IO.popen('cat > /dev/null', 'w+b')
这可能是你想要的,也可能不是,但它应该给你一些关于如何继续的想法