代码之家  ›  专栏  ›  技术社区  ›  user782220

如何在NACL中重定向stdin和stdout?

  •  1
  • user782220  · 技术社区  · 11 年前

    以下更改将nethack-nacl端口从使用nacl装载更新为nacl_io。在nacl挂载版本中,使用JSPipeMount将消息从浏览器引导到 nacl程序的stdin。在nacl_io版本中,这是如何实现的?

    https://chromium.googlesource.com/external/naclports/+/8ac229a6e3fddff3e061017a8eb85105874570b3%5E!/

    1 回复  |  直到 11 年前
        1
  •  4
  •   binji    11 年前

    如提交描述中所述: “浏览器和nexte之间的通信由使用Pepper Simple的TtyNode处理。”

    我在这里回答了同样的问题,并详细介绍了本地客户端讨论谷歌小组: https://groups.google.com/d/msg/native-client-discuss/nOKHWBhBPfs/i_gUYIFuBJAJ

    以下是该帖子的内容:

    在nacl_io中,这只是一个节点( MountNodeTty ),而不是新的安装。您可以通过打开文件“/dev/tty”来访问它。

    最简单的使用方法是使用“ppapi_simple”库。它执行以下操作:

    • 设置 pp::Instance::HandleMessage 将数据转发到节点,然后可以通过读取“/dev/tty”读取该节点
    • 对“/dev/tty”的写入转换为对的调用 pp::Instance::PostMessage .
    • 如果要将stdin和stdout映射到/dev/tty,可以设置 PS_STDIN PS_STDOUT “/dev/tty”的参数。您可以通过向嵌入标记添加其他属性来实现这一点:

      <embed src=“…”type=“application/x-pnacl”PS_STDIN=“/dev/tty”PS_STDOUT=/dev/tty“…>

    要自己完成,您必须执行ppapi_simple库所做的操作。基本上,要将数据馈送到节点中,可以使用对ioctl的调用:

    这是来自pepper_30的代码(src/ppapi_simple/ps_instance.cc:328)。来自pepper_22的代码类似。

    struct tioc_nacl_input_string ioctl_message;
    ioctl_message.length = message_len;
    ioctl_message.buffer = message_str.data();
    int ret =
      ioctl(fd_tty_, TIOCNACLINPUT, reinterpret_cast<char*>(&ioctl_message));
    

    进行节点调用 pp::实例::PostMessage 当您向它写入时,您会使用不同的对ioctl的调用:

    在pepper_30中,这是自动完成的。不过,所有消息都有前缀,所以您可以区分它们。这可以使用ioctl(src/ppapi_simple/ps_instance.cc:210)进行设置:

    const char* tty_prefix = getenv("PS_TTY_PREFIX");
    if (tty_prefix) {
      fd_tty_ = open("/dev/tty", O_WRONLY);
      if (fd_tty_ >= 0) {
        ioctl(fd_tty_, TIOCNACLPREFIX, const_cast<char*>(tty_prefix));
      } else {
        Error("Failed to open /dev/tty.\n");
      }
    }
    

    在pepper_31及更高版本中,必须显式地为tty节点设置回调函数。您可以使用第三个ioctl(src/ppapi_simple/ps_instance.cc:221):

      tioc_nacl_output handler;
      handler.handler = TtyOutputHandlerStatic;
      handler.user_data = this;
      ioctl(tty_fd_, TIOCNACLOUTPUT, reinterpret_cast<char*>(&handler));
    

    最后,如果您想将stdin/stdout重新映射到/dev/tty,那么也必须手动执行。ppapi_sample就是这样做的(src/ppapi_simple/ps_instance:201):

    int fd0 = open(getenv("PS_STDIN"), O_RDONLY);
    dup2(fd0, 0);
    
    int fd1 = open(getenv("PS_STDOUT"), O_WRONLY);
    dup2(fd1, 1);
    

    同样,实现这一点的最简单方法是使用ppapi_simple,或者从该库复制行为。