libuv和uv_try_write:为什么有多个缓冲区?

时间:2016-06-28 13:42:04

标签: c libuv

考虑uv_try_write的文档(同样适用于uv_writeuv_write2)。
声明是:

int uv_try_write(uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs)

uv_buf_t是一个至少包含以下字段的数据结构:

  • char* uv_buf_t.base
  • size_t uv_buf_t.len

我很确定我在这里遗漏了一些东西。

一个人应该提交多个uv_buf_t结构而不是更大结构的原因是什么?
换句话说,如果我有100 char要写出来,我为什么要提交10 uv_buf_t包含每10 char而不是uv_buf_t包含100 char

这样的选择是有意义的真实世界示例会有所帮助,因为我在阅读文档时无法弄清楚它。

2 个答案:

答案 0 :(得分:2)

无论何时执行格式化I / O,您所做的只是串联一串小字符串。

当你写下像

这样的东西时,想想发生在幕后的事情
fprintf(stdout, "Hello, %s!\n", getenv("USER"));

这可以实现(忽略对getenv的多重评估):

struct iovec bufs[3] = {{"Hello, ", 7}, {getenv("USER"), strlen(getenv("USER"))}, {"!\n", 2}};
writev(STDOUT_FILENO, bufs, 3);

(在实践中,FILE操作稍微复杂一些 - 可能是不必要的 - 但大多数情况 这么简单。)

允许直接指定多个缓冲区意味着您不必浪费处理时间(或源代码复杂性),在写入之前分配单个缓冲区来保存它们。

另外,您是否曾在make -j下运行编译器,导致其输出异常混乱?这通常是因为它们这样做 - 而是它们发出几个单独的write并且它们与并行进程的写入混合在一起,而不是在单个系统调用期间发出每一行。 / p>

答案 1 :(得分:1)

大多数应用程序可能使用单个应用程序,但由于writev是我们在try变体中公开它的事情。想象一个应用程序,它充当代理,并在多个数据包中获取数据,然后需要中继。一次性检测属于同一数据包的所有缓冲区将系统调用限制为1,而不必为所有缓冲区分配空间,然后复制内容只是为了调用write

您可以在此处详细了解该方法:https://en.wikipedia.org/wiki/Vectored_I/O