我看到an article为作者建议了以下代码:
output = open("my_pipe", "w+") # the w+ means we don't block
output.puts "hello world"
output.flush # do this when we're done writing data
和读者:
input = open("my_pipe", "r+") # the r+ means we don't block
puts input.gets # will block if there's nothing in the pipe
但open
,puts
,gets
会阻止该计划吗?是否存在某种超时?可以改变吗?另外,w+
如何表示非阻塞呼叫?它转换为哪个open
系统调用标志?
答案 0 :(得分:1)
好的,让我与你分享我对这个世界的看法。正如rogerdpack
所述,有两个选项: 1)在阻塞模式下使用 2)使用非阻塞模式(select
,O_NONBLOCK
标志,{{1 }},read_nonblock
,write_nonblock
方法)。我没试过,所以这些只是推测。
至于为什么select
,open
和puts
可能阻止线程。 gets
调用块,直到至少有一个阅读器和至少一个编写器。这必须是我们需要为open
调用指定r+
,w+
的原因。从open
输出判断,它们都转换为strace
标志。然后必须有一些缓冲区,其中尚未存储接收的数据。这一定是写入方法可能阻塞的原因。读取方法可能会阻塞,因为他们希望有更多数据可用,而不是实际可用。
<强> UPD 强>
如果进程尝试从空管道读取,则read(2)将阻塞,直到数据可用。如果进程尝试写入完整管道(见下文),则写入(2)块,直到从管道读取足够的数据以允许写入完成。
- http://linux.die.net/man/7/pipe
在传递数据之前,必须在两端打开FIFO(读取和写入)。通常,打开FIFO块直到另一端打开。
在Linux下,打开FIFO进行读写将在阻塞和非阻塞模式下成功。 POSIX未定义此行为。这可以用来打开FIFO进行写入,而没有可用的读卡器。
以下是我提出的实施方案:
O_RDWR
但是对于我手边的问题,我决定忽略这个超时的事情。当管道的另一端没有读卡器(Errno :: ENXIO)时,它可能就足以处理这种情况了:
#!/home/yuri/.rbenv/shims/ruby
require 'timeout'
data = ((0..15).to_a.map { |v|
(v < 10 ? '0'.ord + v : 'a'.ord + v - 10).chr
} * 4096 * 2).reduce('', :+)
timeout = 10
start = Time.now
open('1.fifo', File::WRONLY | File::NONBLOCK) { |out|
out.flock(File::LOCK_EX)
nwritten = 0
data_len = data.length
begin
delta = out.write_nonblock data
data = data[delta..-1]
nwritten += delta
rescue IO::WaitWritable, Errno::EINTR
timeout_left = timeout - (Time.now - start)
if timeout_left < 0
puts Time.now - start
raise Timeout::Error
end
IO.select nil, [out], nil, timeout_left
retry
end while nwritten < data_len
}
puts Time.now - start
P.S。感谢您的反馈。
答案 1 :(得分:0)
此页面应该回答您的所有问题...... http://www.ruby-doc.org/core-2.0.0/IO.html
答案 2 :(得分:0)
通常,puts 总是阻止当前线程,因为它们可能必须等待IO完成才能返回。 gets也可以阻止当前线程,因为它将永远读取和读取,直到它到达第一个换行符,然后它将返回它读取的所有内容。 HTH。