带有“ - ”的Ruby IO.popen引擎盖下发生了什么? [英] Ruby IO.popen with "-" , what happens under the hood?

查看:130
本文介绍了带有“ - ”的Ruby IO.popen引擎盖下发生了什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试理解IO.popen,当它的命令是 - 时会启动一个新的Ruby解释器。

I'm trying to understand IO.popen when its command is "-" which starts a new Ruby interpreter.

关于这个主题的材料并不多,我慢慢地通过它们,主要是因为我,因为我只是为了好玩而编码。

There is not much material about this subject, and I'm getting slowly through them, mainly because of me as I only code for fun.

目前为止正如我所理解的那样 IO.popen( - ,w +){| f |调用了}} - 这是一个块 - 该块将由运行父父进程和子进程。不同之处在于父进程将获得一个IO对象,但子进程只有Nil。这很简单,我需要检查块中的 | f | ,当它是Nil时,执行是在子进程中,当它不是nil时,执行在父进程中。所以我必须为父和子编写两个代码,用分隔,如果

As far as I have understood when IO.popen("-", "w+") {|f| ...} is invoked - that's with a block - that block will be run by both the parent and the child process. The difference is that the parent process will get an IO object as a result, but the child gets only a Nil. That's easy, I need to check |f| in the block and when it is Nil, execution is in the child process, when it is not nil, execution is in the parent. So I have to write both code for parent and child separated by if.

这次有助于我理解这个问题,该块是IO.popen命令的一部分

This time it helps me to understand the problem, that the block is part of the IO.popen command.

我有这个代码:

pipe = IO.popen("-","w+")
# puts "This line will break functionality if uncommented"
  if pipe != nil then
    pipe.puts "PID: #{Process.pid}"
    $stderr.puts "Parent from child: #{pipe.gets.chomp}"
  else
    $stderr.puts "Child PID: #{Process.pid} and Parent #{gets.chomp}"
    puts "M'kay"
  end



问题:




  • 什么决定首先运行哪个流程?如果他们要附加一个文件会很容易受到竞争条件的影响吗?

  • 为什么第二行会破坏代码? pipe = IO.popen ... 命令不应与 if..else..end 相关联块,但他们是。对我来说 pipe 是一个文件句柄(就像在旧的Turbo Pascal中一样),它首先在某处定义,然后在别处操作。

  • Questions:

    • What decides which process runs first? If they were to append a file would it be vulnerable to race condition?
    • Why the 2nd line breaks the code? The pipe = IO.popen... command shouldn't be related to the if..else..end block, yet they are. For me pipe is a file handle (like in old Turbo Pascal) which is first definded somewhere, then manipulated elsewhere.
    • 推荐答案

      没有人决定先运行哪个进程。子进程可以先运行 - 或者父进程可以先运行 - 操作系统可以按任意方式安排它们。

      No one decides which process runs first. The child process may run first—or the parent process may run first—OS may schedule them either way.

      这意味着父进程可以在子进程完成之前完成。父进程完成后,将关闭它的管道,当子进程写入它时,它会获得异常。这就是你的代码中发生的事情。

      This means that parent process may finish before the child process finishes. When parent process finishes, the pipe to it is closed, and when the child process writes to it, it gets an exception. That's what happens in your code.

      为什么没有评论线就不会发生?当您在父进程中调用 gets 时,它会等到子进程向管道写入一行。这意味着在孩子将一条线写入管道之前父母将不会完成,这忽略了这个问题。但是,当您打印两行时,父进程在子项执行第二次 之前终止的几率会使M'kay增加。

      Why doesn't it happen without the commented line? When you invoke gets in the parent process, it waits until the child writes a line to the pipe. It means that the parent won't finish until the child writes a line to the pipe, and this neglects the issue. However, when you print two lines, the odds that the parent process terminates before the child executes the second puts "M'kay" increase.

      请尝试以下代码:

      pipe = IO.popen("-","w+")
      puts "This line will not break functionality"
      puts "This line will not break functionality"
      puts "This line will not break functionality"
        if pipe != nil then
          pipe.puts "PID: #{Process.pid}"
          while line = pipe.gets
            $stderr.puts "Parent from child: #{line.chomp}"
          end
        else
          $stderr.puts "Child PID: #{Process.pid} and Parent #{gets.chomp}"
          puts "M'kay"
        end
      

      等待孩子关闭管道(然后是 pipe.gets 将返回 nil ),然后它会终止,并确保它不再尝试在那里写。

      It waits until the child closes the pipe (then the pipe.gets will return nil), which happens then it terminates, and it ensures that it won't try to write there anymore.

      这篇关于带有“ - ”的Ruby IO.popen引擎盖下发生了什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆